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
E
是Enum
的直接(通常是具体)子类,与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 /代码以更好地了解您可以(不)对您执行的操作仍然是间接有用的。