Java的Enum声明是什么意思?

浏览Java的源代码,我发现了以下声明:

public abstract class Enum<E extends Enum> 

应该如何解释? 我坚持下去……

谢谢。

就像quining ! @ LES2走在正确的轨道上。

 public abstract class Foo > { public static void use(Foo foo) { // use foo } } 

如果您有以下课程:

 public class FooImpl extends Foo { // ... } 

然后这些递归模板给你的魔力是:

  • Foo模板要求其参数自身扩展(Foo)。
  • 如果参数类E反过来扩展了Foo (它必须因为前一点),那么你已经确保Foo模板具有其子类的“感知”,因为它的子类作为一个传递给它模板参数
  • 这反过来意味着Foo的方法可以安全地将this指针向下转换为其派生的子类E

你不是一个人。 Ken Arnold 这样说:

或者,为了简单地说明相同点,请考虑这一点:Enum实际上是一个定义为Enum >的generics类。 你搞清楚了。 我们放弃了试图解释它。

(来自博客文章Generics Considered Harmful

使用有界类型的原因可能是由PECS经验法则解释的(在Joshua Bloch的Effective Java中有解释)。

PECS代表“Producer,extends; Consumer super”,它是解释在设计generics方法时如何以及何时使用有界通配符的首字母缩略词。

让我们检查具有此签名的任何抽象类。

 public abstract class Foo > { public static void use(Foo foo) { // use foo } } 

另一个不使用有界通配符的抽象类:

 public abstract class Bar { public static void use(Bar bar) { // use bar } } 

我们的具体课程是:

 public class FooImpl extends Foo { // ... } public class AnotherFooImpl extends Foo { ... } public class BarImpl extends Bar { /// } public class AnotherBarImpl extends Bar { ... } 

我们的主要计划是:

 public class FooBar { public static void main(String[] args) { Foo.use(new FooImpl()); // works Foo.use(new AnotherFooImpl()); // works Bar.use(new BarImpl()); // doesn't work -- why? Bar.use(new AnotherBarImpl()); // doesn't work -- why? } } 

要使Bar.use(new BarImpl())工作,必须使用通配符。

(我想 – 脱离我的头脑 – 我没有编译它,所以我希望我是对的:)

每个枚举元素实际上是枚举类型的子类:

 enum Foo { FooImpl, AnotherFooImpl, ...; } 

基本枚举类中有一些方法需要确保它们具有正确类型的子类,并且为了使其工作,该语法是必要的。

我希望这有帮助(如果你有时间的话,试试这个例子)。

– LES

EEnum的直接(通常是具体)子类,与Comparable(Enum实现Comparable not Comparable )和其他一些方法一起使用。 它这样做是为了访问实际的子类,我怀疑它也需要一些内部实现。

枚举类需要一个参数化类型E,它是Enum的子类。

类型信息E是compareTo(E o)等方法所需要的,它在类声明期间需要类型信息(例如Comparable)。

创建枚举类时,Java编译器会自动传入类型信息,因此在声明时不会看到它

 enum MyType {...} 

有些事情我不喜欢generics的使用方式。 例如,当接口只需要类信息时,为什么我们需要将类类型详细地传递给接口? 我们不能有默认值,或者编译器现在不够智能?

例如

 class String implements Comparable 

此类不是枚举器类型。 它只是一个复杂的通用常规类。 很难说(没有看到整个代码)为什么它是这样的设计。 但是当你想要一个总是返回当前类型的方法时,我猜它可能与自我类型的概念有关。

 public abstract class Enum> { E getMe() { return (E)this; } } public class E1 extends Enum { void doE2_only() {} void doE2() { // This line is to prove that Javac will see this.getMe() as a function of E1 this.getMe().doE2_only(); } } public class E2 extends Enum { void doE2_only() {} void doE2() { // This line is to prove that Javac will see this.getMe() as a function of E2 this.getMe().doE2_only(); } } 

这又与枚举器类型无关。

只是一个thougth;

您在代码中创建的所有枚举都将由扩展Enum类的最终类创建。

 public enum MyEnum { XYZ } 

会变成

 public final class MyEnum extends Enum 

或类似的东西(不确定XYZ是否成为实例或扩展它的类 – 我也认为它不是最终的,但编译器不会让你扩展枚举)…无论如何,因为这样的枚举不是真的很有用,因为你不能(不应该)自己“做”任何事情。

阅读其javadoc /代码以更好地了解您可以(不)对您执行的操作仍然是间接有用的。