2011-08-29 183 views
3

我读通过莫卧儿(第3版)(最好的SCJP的书,我所遇到的)和727页上的SCJP,它说以下内容:Java泛型:子类化一个通用的超类 - 子类是一个可定义的类型?

class MyIntList extends ArrayList <Integer> {} // A reifiable subclass 

现在我在这里只是有点疑惑。我知道子类属于非泛型类型,但由于它扩展了ArrayList < Integer>和参数化的< Integer>将最终被擦除,并且此子类将继承其超类的属性,为什么这个子类MyIntList是可重用类型?

+0

无论如何,这种区分在这种情况下如何重要?很明显,新的MyIntList().getClass()== MyIntList.class'不会丢失任何信息(因为还有什么可能呢?) - 它是否正确地将单词“reifiable”赋值给它还是不? –

+1

您似乎认为在这种情况下,'MyIntList'会在运行时将其超类参数''擦除。不是这种情况。泛型类的具体子类保留其超类泛型参数的类型信息。这使得一些[非常漂亮的技巧]成为可能(http://gafter.blogspot.com/2006/12/super-type-tokens.html)。 –

+0

@亨宁,想想所有的工具,测试等可以写在一个约束列表。 –

回答

3

因为MyIntList的每个实例都是Array<Integer>,所以可以使用反射来找出下限/上限。

如果您说class MyNumberList<T extends Number> extends ArrayList<T> { ... },您仍然可以找到边界,但不是T对于MyNumberList的特定实例。

+0

但参数化的已被删除 – yapkm01

+3

@ yapkm01:不是。泛型类型的特定参数化的非泛型子类型没有删除该参数化。 –

+0

@ yapkm01构建直觉的一种方法是考虑*实例*。如果你有一个'ArrayList'的实例,你不知道'T'是什么。但是每个MyIntList实例总是一个ArrayList 。换句话说,Java不会创建一个对应于你的'ArrayList '的新'Class'。但是参数类型被烘焙到'MyIntList'的'Class'中。 –

3

从Java语言规范 http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html

4.7 Reifiable类型

由于某些类型的信息在编译时擦除,不是所有类型的都可以在运行时。运行时完全可用的类型称为可重用类型。只有在以下情况之一成立的情况下,类型才可认证:

  • 它引用了非泛型类型声明。
  • 它是一个参数化类型,其中所有类型参数都是无界通配符(§4.5.1)。
  • 它是一种原始类型(§4.8)。
  • 它是一种原始类型(§4.2)。
  • 它是一个数组类型(§10.1),其组件类型是可调整的。
0

泛型类型在编译ArrayList期间被擦除,但不在编译MyIntList期间被擦除。所以在运行时你可以通过调用MyIntList.class.getGenericSuperclass()并分析返回的对象来发现MyIntList扩展了ArrayList。

这是可能的原因是MyIntList本身不是通用的,但扩展了ArrayList的具体实例。所以这些信息可以存储在MyIntList的Class对象中(使用上面提到的方法可以访问它)。

相关问题