扩展通用类
public class MyGeneric<T, E> {} public class Extend1<T, E> extends MyGeneric<T, E> {} public class Extend2 extends MyGeneric<String, Object> {}
据我所知,上例中的两个子类都是有效的。 我想知道Java是如何知道什么时候在超类中给出的types将在子类被实例化的时候被定义,以及当它们是实际的类名时(即它如何知道T,E不是类名)?
一个侧面说明,是否允许(即使不常见)使用多个字母的genericstypes? 如果(通过一些严重的计划错误)如果types与现有的类相冲突,例如
public class E{} public class Foo<E>{}
那么会发生什么?
编辑:谢谢你这么及时回答。 为了回答我的第一个问题, Joachim的答案是最有效的。
为了回答这个问题, aioobe的答案更为清晰
我们来看这个定义:
public class Extend1<T, E> extends MyGeneric<T, E> {}
这里T
和E
每个出现两次,分两个不同的angular色
- 在
Extend1<T,E>
定义了types参数。 这意味着typesExtend1
有两个(无界)types参数T
和E
这告诉Java编译器,那些使用Extend1
需要指定types。 - 在
extends MyGeneric<T,E>
你使用以前定义的types参数。 如果T
和E
在这里不是types参数,那么T
和E
就是简单的types引用,即编译器会寻找名为T
和E
类(或接口,…)(很可能不会find它们) 。
是的,types参数遵循与Java中任何其他标识符相同的语法规则,所以你可以使用多个字母ABC
甚至可能混淆的名字(使用称为String
的types参数是合法的,但是非常混乱)。
单字母types的参数名称只是一个非常常见的命名策略。
我想知道Java是如何知道什么时候在超类中给出的types将在子类被实例化的时候被定义的,以及当它们是实际的类名时(即它如何知道T,E不是类名)?
Java不关心。 如果你这样做…
class MyGeneric<String> extends ArrayList<String> { String value; }
是否允许(即使不常见)为generics使用多个字母? 如果(通过一些严重的计划错误)如果types与现有的类相冲突,例如
是的,您可以使用任何有效的Java标识符作为types参数。
名称可能有冲突,但Java不会将其视为错误。 无论标识符是否与类名相对应, <
… >
之间的标识符将始终被视为types参数。
可能会让人感到困惑。 这是一个例子:
class MyGeneric<String> extends java.util.ArrayList<String> { String value; } class Test { public static void main(String... args) throws Exception { MyGeneric<Integer> obj = new MyGeneric<Integer>(); obj.value = 5; // ^ // | // '--- Assign an integer to what seems to be a String! } }
类似的问题:
- 拆箱问题
没有问题:
public class E{} public class Foo<E>{}
因为在Foo<E>
的上下文中, E
是一个types。