public class MyGeneric<T, E> {}
public class Extend1<T, E> extends MyGeneric<T, E> {}
public class Extend2 extends MyGeneric<String, Object> {}
据我所知,上例中的两个子类都是有效的。我想知道Java何时知道何时在实例化子类时定义超类中给出的类型,以及何时它们是实际的类名(即它如何知道T,E不是类名)?
附注,是否允许(即使不常见)为泛型类型使用多个字母?如果(通过计划的某些严重错误)类型与现有类冲突,例如
public class E{}
public class Foo<E>{}
然后会发生什么?
编辑:感谢您及时回答。 要回答我的第一个问题,Joachim's answer是最有效的。
答案 0 :(得分:58)
让我们来看看这个定义:
public class Extend1<T, E> extends MyGeneric<T, E> {}
此处T
和E
分别出现两次,分为两个不同的角色
Extend1<T,E>
中定义类型参数。这意味着类型Extend1
具有两个(无界)类型参数T
和E
。 这告诉Java编译器那些使用 Extend1
的人需要指定类型。extends MyGeneric<T,E>
中使用以前定义的类型参数。如果此处不知道T
和E
是类型参数,那么T
和E
将是简单类型引用,即编译器将查找类(或接口, ...)名为T
和E
(很可能找不到它们)。是的,类型参数遵循与Java中任何其他标识符相同的语法规则,因此您可以使用多个字母ABC
甚至可能令人困惑的名称(使用名为String
的类型参数是合法的,但高度令人困惑。)
单字母类型参数名称只是一种非常常见的命名策略。
答案 1 :(得分:22)
我想知道Java如何确定何时在子类被实例化时定义超类中给出的类型,以及当它们是实际的类名时(即它如何知道T,E是不是班级名单)?
Java并不关心。如果你这样做......
class MyGeneric<String> extends ArrayList<String> {
String value;
}
是否允许(即使不常见)为泛型类型使用多个字母?如果(通过计划的某些严重错误)类型与现有类冲突,例如
是的,您可以使用任何有效的Java标识符作为类型参数。
名称可能存在冲突,但Java不会将此视为错误。 <
... >
之间的标识符将始终被视为类型参数,无论标识符是否与类名相对应。
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!
}
}
类似的问题:
答案 2 :(得分:2)
没有问题:
public class E{}
public class Foo<E>{}
因为在Foo<E>
的上下文中,E
是一种类型。