一个枚举常量包含了同一个枚举类中的所有枚举常量。

22

我刚意识到Java中的枚举常量似乎包含了同一类型的所有枚举常量。

例如,以下代码是合法的:

enum State {
    enable, disable, deleted;
}

class Test {
    public static void main(String[] args) {
        for ( State s : State.enable.disable.values() ) {
            System.out.println(s);
         }
    }
}

当我看到输出结果是以下内容时,我感到非常惊讶:

enable
disable
deleted

enable 常量包含 disable 常量,而 disable 常量又包含所有的 State 枚举常量,这难道不是违反直觉甚至有些荒谬吗?

这种语言设计背后可能有哪些考虑?


与此相关的内容:https://dev59.com/WnRB5IYBdhLWcg3weXOX - Naitree
10
请开启警告提示:“静态字段State.disable应该以静态方式访问。” - maaartinus
3个回答

35

在设计Java时,设计师犯了一个错误:静态成员属于类本身,而不属于类的任何实例,但可以使用该类的实例进行访问。考虑以下类:

Designers made a mistake when they first designed Java: static members, which belong to the class itself, and not to any instance of the class, can be accessible using an instance of the class. consider this class:

class Foo {
    public static int bar = 0;
}

通常应使用bar变量进行访问。

int i = Foo.bar;

但你也能够去做

Foo foo = new Foo();
int i = foo.bar;

这就是这里正在发生的事情。 enabledisablevalues() 是类 State 的静态成员,应该使用 State.enableState.disableState.values() 进行访问。但是 enabledisable 也是类 State 的实例,因此也可以用于访问类的静态成员:

State state = State.enable;
State state2 = state.disable;

更简单地说:

State state2 = State.enable.disable;

你甚至可以这样做,而不会出现NullPointerException:

State state = null;
State[] allStates = state.values();

这不是一个错误,在编译时编译器会用类名替换实例变量。 - Yurets
@Yurets JB并不是在暗示编译器出错了,而是Java的设计者犯了一个错误。 - user253751

13

values() 是一个静态方法。Java语言允许您在该类的任何实例上调用类的静态方法,但会忽略实例。

enabledisabledeleted 也是静态字段。

State.enable 并不包含 disable,相反,State.enable.disableState.disable 相同。而 State.enable.disable.values() 的处理方式与 State.disable.values() 相同,它们都与 State.values() 相同,当然会返回所有三个值的数组。


4

.values()enum 上的隐式 static 方法,无论你在哪个值上调用它,都会得到与 State.values() 相同的结果。

这几乎就像在实例上调用静态方法(而不是直接引用类名)一样。

实际上,在实例上调用 static 方法应该会引发警告,提示你正在不当地使用该方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接