Java';什么是枚举声明?

Java';什么是枚举声明?,java,generics,Java,Generics,在浏览Java的源代码时,我发现了以下声明: public abstract class Enum<E extends Enum<E>> 公共抽象类枚举 应该如何解释?我被它困住了 谢谢你。你并不孤单。我不得不说: 或者,简单地说,说明同样的观点, 考虑一下:EnUM实际上是一个 泛型类定义为枚举。你认为 把它弄出来。我们放弃了解释 它 (来自被认为有害的博客条目泛型)Enum类需要一个参数化类型E,它是Enum的子类 compareTo(EO)之类的方法需要类型信息

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

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

公共抽象类枚举
应该如何解释?我被它困住了

谢谢你。

你并不孤单。我不得不说:

或者,简单地说,说明同样的观点, 考虑一下:EnUM实际上是一个 泛型类定义为枚举。你认为 把它弄出来。我们放弃了解释 它


(来自被认为有害的博客条目泛型)

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

compareTo(EO)之类的方法需要类型信息E,它在类声明期间需要类型信息(例如Comparable)

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

enum MyType {...}
有些东西我不喜欢通用的用法。例如,当接口只需要类信息时,为什么我们需要将类类型详细地传递给接口?我们不能有默认值,或者编译器现在不够聪明

e、 g

类字符串实现了可比较的

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

此类不是枚举器类型。它只是一个复杂的泛型正则类。很难说(没有看到全部代码)它为什么是这样设计的。但是我猜这可能与self类型的概念有关,因为您希望有一个方法始终返回当前类型


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();
    }
}

公共抽象类枚举{
E getMe(){返回(E)this;}
}
公共类E1扩展了Enum{
void doE2_only(){}
无效doE2(){
//这一行是为了证明Javac将把这个.getMe()看作E1的函数
这个.getMe().doE2_only();
}
}
公共类E2扩展了枚举{
void doE2_only(){}
无效doE2(){
//这一行是为了证明Javac将把这个.getMe()看作是E2的函数
这个.getMe().doE2_only();
}
}
同样,这与枚举数类型无关


只是一个想法

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

public enum MyEnum { XYZ }
将成为

public final class MyEnum extends Enum<MyEnum>
public final类MyEnum扩展了Enum
或者类似的东西(不确定XYZ是否成为一个实例或一个扩展它的类-我也认为它不是真正的最终版本,但编译器不允许您扩展枚举)。。。无论如何,这样的枚举并不是真正有用的,因为您自己不能(不应该)真正“做”任何事情


阅读它的javadoc/代码,更好地理解您可以(不可以)对枚举做什么,这仍然是间接有用的。

使用绑定类型>的原因可能是由PECS经验法则解释的(Joshua Bloch用有效的Java解释)


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

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

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

   public static void use(Foo<E> foo) {
      // use foo
   }
}
要使Bar.use(new BarImpl())工作,必须使用通配符

(我想不到,我还没有编译它,所以我希望我是对的:)

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

enum Foo {
   FooImpl, AnotherFooImpl, ...;
}
基本枚举类中有一些方法需要确保它们具有正确类型的子类,而要使其正常工作,语法是必需的

我希望这能有所帮助(如果你有时间,试试这个例子)

-- LES

就像@第二课是正确的

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

   public static void use(Foo<E> foo) {
      // use foo
   }
}
公共抽象类Foo
{
公共静态无效使用(Foo-Foo){
//使用foo
}
}
如果您有以下课程:

public class FooImpl extends Foo<FooImpl> {
  // ...
}
public类FooImpl扩展了Foo{
// ...
}
这些递归模板给你的魔力是:

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

嗯。“enum”关键字是在后台使用类enum实现的。经过一些调查,它似乎是您所说的enum类型的后端。为什么与java.lang.enum相同的构造无法编译?javac正在阻止它吗?为什么会这样?对不起,你所说的“为什么与java.lang.Enum相同的构造“不编译”是什么意思?你的意思是你创建了一个类似的结构类,但它没有编译?我试过了(我发布的代码已编译并运行)你会详细阐述吗?<代码>公共抽象类EnUM/代码>对于你正在做的工作也很有用。谢谢你的链接。我很高兴我并不孤单:谢谢你给我的所有令人印象深刻的输入。我认为每一个答案都很有趣(所以我给了你一个+1)。:)看起来像Java版本的Hi@LES2!谢谢你的回答,但我无法编译Foo,因为它说“use”方法不能“对非静态类型E进行静态引用”。Bar class.public static也是如此它是一个首字母缩略词,解释了在设计泛型方法时如何以及何时使用有界通配符。“是的,这里没有通配符。
publicstaticvoiduse(Foo-Foo)
publicstaticvoiduse(Bar)
不按编写的方式编译(您尝试过吗?)。它们不在
E
的范围内。”这反过来意味着Foo的方法可以
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?
   }
}
enum Foo {
   FooImpl, AnotherFooImpl, ...;
}
public abstract class Foo <E extends Foo<E>> 
{

   public static void use(Foo<E> foo) {
      // use foo
   }
}
public class FooImpl extends Foo<FooImpl> {
  // ...
}