扩展泛型类

2022-08-31 15:22:52
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>{}

然后会发生什么?

编辑:感谢您如此迅速地回答。为了回答我的第一个问题,约阿希姆的答案是最有效的。

为了回答题外话,aioobe的答案更清晰


答案 1

让我们看一下这个定义:

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

在这里,每个人都出现了两次,并扮演着两个不同的角色TE

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

是的,类型参数遵循与Java中任何其他标识符相同的语法规则,因此您可以使用多个字母甚至可能令人困惑的名称(使用称为的类型参数是合法的,但非常令人困惑)。ABCString

单字母类型参数名称只是一种非常常见的命名策略。


答案 2

我想知道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!
    }
}

类似的问题: