Java的Enum声明是什么意思?

时间:2009-10-01 17:22:16

标签: java generics

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

public abstract class Enum<E extends Enum<E>>

应如何解释?我坚持不懈......

谢谢。

7 个答案:

答案 0 :(得分:2)

你并不孤单。 Ken Arnoldthis说:

  

或者,简要地说明一点,   考虑一下:Enum实际上是一个   泛型类定义为Enum&lt; T   扩展Enum&lt; T&gt;&gt;。你想   出来。我们放弃了试图解释   它

(来自博客条目 Generics Considered Harmful

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

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

public abstract class Foo <E extends Foo<E>> {

   public static void use(Foo<E> foo) {
      // use foo
   }
}

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

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

我们的具体课程是:

public class FooImpl extends Foo<FooImpl> {
  // ...
}
public class AnotherFooImpl extends Foo<AnotherFooImpl> { ... }

public class BarImpl extends Bar<BarImpl> {
   ///
}

public class AnotherBarImpl extends Bar<AnotherBarImpl> { ... }

我们的主要计划是:

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

答案 3 :(得分:1)

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

public abstract class Foo <E extends Foo<E>> 
{

   public static void use(Foo<E> foo) {
      // use foo
   }
}

如果您有以下课程:

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

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

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

答案 4 :(得分:-1)

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

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

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

enum MyType {...}

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

e.g。

class String implements Comparable<String>

答案 5 :(得分:-1)

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


public abstract class Enum<E extends Enum<E>> {
    E getMe() { return (E)this; }
}
public class E1 extends Enum<E1> {
    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<E2> {
    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();
    }
}

这又与枚举器类型无关。

只是一个人;

答案 6 :(得分:-1)

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

public enum MyEnum { XYZ }

将成为

public final class MyEnum extends Enum<MyEnum>

或类似的东西(不确定XYZ是否成为实例或扩展它的类 - 我也认为它不是真的 final,而是编译器不会让你扩展枚举)。 ..无论如何,因为Enum并不是真的有用,因为你不能(不应该)自己“做”任何事情。

阅读其javadoc /代码以更好地了解你可以(不)对你的枚举做什么仍然是间接有用的。