扩展通用类

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> {} 

这里TE每个出现两次,分两个不同的angular色

  • Extend1<T,E> 定义了types参数。 这意味着typesExtend1有两个(无界)types参数TE 告诉Java编译器,那些使用 Extend1需要指定types。
  • extends MyGeneric<T,E>使用以前定义的types参数。 如果TE在这里不是types参数,那么TE就是简单的types引用,即编译器会寻找名为TE类(或接口,…)(很可能不会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。