为什么我不能在 java java.lang.Enum 泛型类型定义中重现?

Sja*_*aak 0 java generics enums

这是一个学术问题,旨在更好地理解泛型在这种情况下的行为。

Enum类型被描述为“所有 Java 语言枚举类型的公共基类”。它的定义是:

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {

} 
Run Code Online (Sandbox Code Playgroud)

现在,我可以用这个定义定义一个字段:

public class MyClass { 
   public Enum<MyEnum> field;
}
Run Code Online (Sandbox Code Playgroud)

一切都很好。现在,更进一步。因为Enum<MyEnum>显然等同于MyEnum这会让我相信根据定义我也可以写:

public class MyClass { 
   public Enum<Enum<MyEnum>> field;
}
Run Code Online (Sandbox Code Playgroud)

但是现在编译器实际上阻止了我:Type parameter 'java.lang.Enum' is not within its bound; should extend 'java.lang.Enum<MyEnum>>它根据定义进行操作,因为它仍然满足:E extends Enum<E>。当然,您不允许这种重复(或者可能更好,发生)构造的原因有很多,但给出的一个对我来说确实是错误的。

另一方面,如果我要定义一个这样的类(类似于 的定义Enum

public class Wrapper<T extends Number> { 
} 
Run Code Online (Sandbox Code Playgroud)

我将能够编写一个类:

public class Wrapper<T extends Number> { 
} 
Run Code Online (Sandbox Code Playgroud)

我是忽略了什么还是我的分析被误导了?

Joh*_*ica 6

我认为这是一个学术问题。你实际上并不是在写这样的代码,你只是想更好地理解语言,对吧?因为在实际代码中,您当然会简单地编写:

public MyEnum myField;
Run Code Online (Sandbox Code Playgroud)

本着这种精神——

因为Enum<MyEnum>显然等价于MyEnum...

它们不是等价的。MyEnum是一个子类Enum<MyEnum>。自动生成的类是这样的:

public final class MyEnum extends Enum<MyEnum> {
    ...
}
Run Code Online (Sandbox Code Playgroud)

这意味着您不能继续使用Enum<Enum<MyEnum>>. 如果你愿意,你可以这样写:

public Enum<? extends Enum<MyEnum>> field;
Run Code Online (Sandbox Code Playgroud)

那将编译,并且递归的可能性到此为止。

我理解的上限是什么XT extends X它包括X和它的子类。所以Enum<Enum>应该被允许,但事实并非如此。

让我们来看看究竟是什么EE从这里:

public abstract class Enum<E extends Enum<E>>
Run Code Online (Sandbox Code Playgroud)

当你写Enum<Enum<MyEnum>>EEnum<MyEnum>。这E与约束匹配E extends Enum<E>吗?我们需要替换E使用Enum<MyEnum>

E extends Enum<E>?
^              ^

Enum<MyEnum> extends Enum<Enum<MyEnum>>?
^^^^^^^^^^^^              ^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

现在让我们回答几个相关但略有不同的问题:

  • 是否MyEnum延长Enum<MyEnum>?是的。我上面列出的自动生成的代码显示了这种情况。

  • 是否Enum<MyEnum>延长Enum<MyEnum>?是的。正如您在Number示例中正确描述的那样,就extends关键字而言,类被认为是其自身的子类。

  • 现在我们现在关心的问题是:是否Enum<MyEnum>扩展Enum<Enum<MyEnum>>?不,它没有。这是为了让您尝试工作的代码需要保持的关系。它不成立,这就是您的代码无法编译的原因。