扩展通用类

时间:2011-08-31 10:26:51

标签: java class generics subclassing

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是最有效的。

回答要点aioobe's answer is clearer

3 个答案:

答案 0 :(得分:58)

让我们来看看这个定义:

public class Extend1<T, E> extends MyGeneric<T, E> {}

此处TE分别出现两次,分为两个不同的角色

  • Extend1<T,E>定义类型参数。这意味着类型Extend1具有两个(无界)类型参数TE告诉Java编译器那些使用 Extend1的人需要指定类型。
  • extends MyGeneric<T,E>使用以前定义的类型参数。如果此处不知道TE是类型参数,那么TE将是简单类型引用,即编译器将查找类(或接口, ...)名为TE(很可能找不到它们)。

是的,类型参数遵循与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是一种类型。