8

我知道这不是一个好问题,我可能会被诅咒问这个问题,但我找不到任何地方可以在这​​个问题上获得帮助

下面是我的面试问题中出现的一个通用类(我已经失败了)。问题是要说明这个 Class 声明在做什么以及在什么情况下可以使用它?

我对通用编程的理解非常有限,但我知道“T”是类型,而“扩展”在这里意味着类型应该继承了“SimpleGenericClass”,但我不明白“?” 最后以及在什么情况下这个类可能被用于

public abstract class SimpleGenericClass<T extends SimpleGenericClass<?>> {

}
4

5 回答 5

4

首先,因为类SimpleGenericClass抽象的,所以它是子类的。

其次,它是一个泛型类,这意味着在类内部的某个地方,您几乎肯定会使用泛型参数T作为字段的类型。

public abstract class SimpleGenericClass<T...> {
    T x;
}

现在第一个有趣的事情T有界的。因为它被声明为T extends SimpleGenericClass<?>只能SimpleGenericClass<?>SimpleGenericClass<?>. 您还询问了 thr ?这被称为通配符, Java Tutorial on Wildcards中有一个很好的解释。在您的情况下,我们会说这是“未知的 SimpleGenericClass”。例如,它在 Java 中是必需的,因为SimpleGenericClass<Object>它不是 的超类SimpleGenericClass<String>

第二有趣的事情是,由于TSimpleGenericClass某种类型的,你的类很可能定义 递归结构。我想到的是树(想想表达式树),其中SimpleGenericClass(抽象)节点类型是(抽象的)节点类型,旨在与各种专门的节点类型进行子类化。

更新 This SO question on self-bounded generics可能对您有所帮助。

更新 2

我继续整理了一些代码来说明如何使用它。该应用程序不做任何事情,但它会编译,它会向您展示通用边界如何提供一些可能有意义的约束。

public abstract class Node<T extends Node<?>> {
    public abstract T[] getChildren();
}

class NumberNode extends Node {
    int data;
    public Node[] getChildren() {return new Node[]{};}
}

class IdentifierNode extends Node {
    int data;
    public Node[] getChildren() {return new Node[]{};}
}

class PlusNode extends Node {
    NumberNode left;
    NumberNode right;
    public NumberNode[] getChildren() {return new NumberNode[]{};}
}

这里的好处是这NumberNode[]是一个有效的返回类型PlusNode.getChildren!这在实践中重要吗?不知道,但它很酷。:)

这不是最好的例子,但问题是相当开放的(“这样的东西可以用来做什么?”)。当然,还有其他定义树的方法。

于 2011-09-24T07:43:24.257 回答
0

这实际上仅意味着您允许 SimpleGenericClass 类的用户参数化类型为 T 的类的实例。但是,T 不能是任何类型,而必须是 SampleGenericClass(或 SampleGenericClass 本身)的子类型。

在 SimpleGenericClass 类的其余代码中,您可以在方法签名中使用类型 T。

让我们假设 SimpleGenericClass 不是抽象的。使用它时,您可以编写:

new SimpleGenericClass<SampleGenericClass<String>>();

即你用SampleGenericClass 参数化SimpleGenericClass 和用String 参数化SampleGenericClass。

于 2011-09-24T07:26:25.283 回答
0

根据定义,它SimpleGenericClass可以在<T>SimpleGenericClass 的子类上工作。

所以我认为会有一些操作可以在<T>.

现在看看为什么要定义这样的模板 - (我真的想不到太多)可能SimpleGenericClass是一个抽象类的场景(刚刚意识到它是按照 OP :P)并期望它可以工作任何具体的课程?

伙计们,你们怎么看?

于 2011-09-24T07:43:13.747 回答
0

这基本上是这样的:在这个类中,你有一个名为 T 的 Type 占位符,并且对该占位符有一个限制,它必须是 SimpleGenericClass 类型或扩展它的东西。一旦你遵守了这条规则,你就可以创建你的类的实例并给 T 一个实际的类型,以后可以在该类的方法中使用它,如下所示:

public class C <T extends Number>{

    public void doSomething(T t) {

    }

    public static void main(String... args) {
        //works:
        C<Number> c = new C<Number>();
        c.doSomething(new Number() {
            //Aonimous implementation of number

        });

        //won't work
        //C<Object> c = new C<Object>();

        C<Integer> c2 = new C<Integer>();       
        c2.doSomething(new Integer(1));
        //won't work
        //c2.doSomething(new Number() {

            //Aonimous implementation of number
        //});
    }
}

在这 SimpleGenericClass<?>一点上是相当多余的。如果此类需要另一种泛型类型,则可以有多个 ( SimpleGenericClass<T extends SimpleGenericClass, T2 extends Whatever>)

于 2011-09-24T07:44:43.060 回答
0

我猜你有这种形式的问题(T而不是?):

public abstract class SimpleGenericClass<T extends SimpleGenericClass<T>>

看看这段代码:

abstract class Foo<SubClassOfFoo extends Foo<SubClassOfFoo>>
{
    /** subclasses are forced to return themselves from this method */
    public abstract SubClassOfFoo subclassAwareDeepCopy();
}

class Bar extends Foo<Bar> {
    public Bar subclassAwareDeepCopy() {
        Bar b = new Bar();
        // ...
        return b;
    }
}

Bar b = new Bar();
Foo<Bar> f = b;
Bar b2 = b.subclassAwareDeepCopy();
Bar b3 = f.subclassAwareDeepCopy(); // no need to cast, return type is Bar

诀窍Foo<SubClassOfFoo extends Foo<SubClassOfFoo>>是:

  • 的任何子类都Foo必须为Foo.
  • 该类型参数实际上必须是Foo.
  • Foo(like ) 的子类Bar遵循它们提供的类型参数Foo就是它们自己的习语。

  • Foo 有一个返回的方法SubClassOfFoo。结合上述成语,这允许 Foo 制定一个契约,上面写着“我的任何子类都必须实现subclassAwareDeepCopy(),并且他们必须声明它返回那个实际的子类”。

换一种说法:这个习惯用法允许超类(例如抽象工厂)定义其参数类型和返回类型是根据子类类型而不是超类类型的方法。

这个技巧例如在EnumJDK 类中完成:

public abstract class Enum<E extends Enum<E>>

有关详细信息,请参阅此处

于 2011-09-24T07:59:04.280 回答