与Enum类型混淆

时间:2011-10-18 04:46:56

标签: java

为什么当我定义枚举时,我传递一个字段名称列表,然后不知何故那些字段名称(例如Days.MONDAY)最终引用字段?我可以传递一个字段(例如Days.MONDAY)然后使用开关来获取字段值。更奇怪的是,当我声明枚举字段时,我甚至不必将名字放在引号中,即使它们实际上是值。

3 个答案:

答案 0 :(得分:5)

Java中的枚举与其他语言中的枚举不同。他们需要一些使用。从本质上讲,枚举是一个特殊的类,你声明的每个枚举都是该类的一个对象:

public enum Day {

    MONDAY, TUESDAY, WEDNESDAY

}

MONDAY,TUESDAY和WEDNESDAY是Class Day的对象,使用普通类可以获得几乎相同的效果,但是enum语法明确了你的意图。此外,您无法在其他地方创建THURSDAY - 仅在枚举括号内。这意味着编译器始终知道枚举值的完整列表,并允许Java在switch语句等地方使用枚举,因为编译器具有创建跳转表和检查代码正确性所需的所有信息。

因此,MONDAY 某个整数值的标签,例如其他语言的枚举。它是一个像任何其他Java对象一样的对象。这就是为什么你不把它们放在引号中。这就像写作:

final static Day MONDAY = new Day();
final static Day TUESDAY = new Day();

等等。你甚至可以做这样的技巧:

public enum Day {

    MONDAY("Mon", false), TUESDAY("Tue", false), WEDNESDAY("Wed", true);

    private String shortForm = null;
    private boolean humpDay = false;

    Day(String shortForm, boolean humpDay) {
        this.shortForm = shortForm;
        this.humpDay=humpDay;
    }

    public String getShortForm() {
        return shortForm;
    }

    public boolean isHumpDay() {
        return humpDay;
    }

}

每个星期一,星期二,星期三都是Day的对象,每个都有自己的成员,包括shortForm和humpDay。甚至还有一个构造函数。看到?对象,而不是值。

需要TUESDAY的简短表格吗?只需要做TUESDAY.getShortForm()。你不能用其他语言中的重新标记整数常数范式来做到这一点。

我希望有所帮助。 Java枚举非常强大,但对于习惯于使用其他语言的枚举的人来说,直到他们有突破性的时刻(“我现在看到它们!它们就像对象声明!”)可能会让人感到困惑。

答案 1 :(得分:3)

将Java枚举视为定义类的一种很好的语法。这是一个可能有帮助的shell脚本:

$ cat > Direction.java
public enum Direction {NORTH, EAST, SOUTH, WEST}
$ javac Direction.java 
$ javap Direction
Compiled from "Direction.java"
public final class Direction extends java.lang.Enum{
    public static final Direction NORTH;
    public static final Direction EAST;
    public static final Direction SOUTH;
    public static final Direction WEST;
    public static Direction[] values();
    public static Direction valueOf(java.lang.String);
    static {};
}

是的,您可以说EAST是类Direction的字段,其值是类Direction的实例。我们将此值称为Direction.EAST,与通过任何其他类的静态字段引用值的方式相同。

也许这种混淆是由于您没有看到像

这样的声明
public static final Direction.EAST = SOMETHING_OR_OTHER_HERE;

这是可以理解的。枚举用于初始化这些字段值,但您不必自己显式初始化它们。就像你说的那样

public static final Direction.EAST = new Direction();

事实上,它是所谓的“Typesafe Enum”模式的一部分,它在Java获得当前枚举语法之前通常使用。

关于你对引号的评论,根本没有理由引用任何内容,因为没有涉及字符串。

关于你关于开关的评论,是的,字段名称和字段值的概念如何在这里发挥作用有点有趣。但这只是因为该值看起来像字段。换句话说,EAST中的字段Direction的值就是Direction.EAST。但是,如果你考虑它,它与文字没有太大区别。您可能会问Float.NaN的价值是多少?嗯,它是...... Float.NaN。一种不透明的价值。

答案 2 :(得分:-1)

我认为enum的方式是它只是一个具有别名的唯一值的“列表” - 名称。几天你可以有从1到7的整数数组,但是在你的代码中,将名称分配给代表对象的事物,即星期一,星期二等,会更方便。等等你也可以为每一天宣布常量一周,但你必须输入更多的代码。 enum似乎没有像类那样引入一些新的编程范例,只是一个方便的快捷工具。