【发布时间】:2010-10-18 02:09:58
【问题描述】:
在 Java 中,Enum 可以做 Enums 所做的伟大事情,但也可以有方法(行为和逻辑)。与使用枚举的类相比,这有什么优势?也欢迎简单的例子来说明这一点。
【问题讨论】:
在 Java 中,Enum 可以做 Enums 所做的伟大事情,但也可以有方法(行为和逻辑)。与使用枚举的类相比,这有什么优势?也欢迎简单的例子来说明这一点。
【问题讨论】:
看看 java/joda 时间类,枚举在其中做了很多工作。
这里是 java.time.Month 的一个例子:
public enum Month implements TemporalAccessor, TemporalAdjuster {
JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER;
private static final Month[] ENUMS = Month.values();
public static Month of(int month) {
if (month < 1 || month > 12) {
throw new DateTimeException("Invalid value for MonthOfYear: " + month);
}
return ENUMS[month - 1];
}
// About a dozen of other useful methods go here
}
【讨论】:
基本上,Java 枚举 是 类(我认为在字节码级别没有区别),另外还有一个好处是拥有一组已知的固定可能实例并能够使用它们在 switch 语句中。
您可以使用常规类模拟“已知的固定可能实例集”(无数书籍和文章中描述的“类型安全枚举”模式),但要使其正常工作需要做很多工作(对每个此类重复)关于序列化、equals() 和 hashCode() 以及我可能忘记的其他一些事情,确实是正确的。语言级别的枚举让您免于工作。而且,如上所述,switch 语句中只能使用语言级别的枚举。
【讨论】:
因为枚举实例是单例,您可以在switch 语句中使用它们或与== 一起使用来检查相等性。
【讨论】:
Enum 类型也是实现真正单例的好方法。
Java 中的经典单例模式通常涉及私有构造函数和公共静态工厂方法,但仍然容易通过反射或(反)序列化进行实例化。枚举类型可以防止这种情况发生。
【讨论】:
这是一个简单的例子:
enum RoundingMode {
UP {
public double round(double d) {
return Math.ceil(d);
}
},
DOWN {
public double round(double d) {
return Math.floor(d);
}
};
public abstract double round(double d);
}
【讨论】:
在我们的项目中,我们将 Enums 用于一些事情,但也许最重要的是用于 i18n 目的 - 每条显示的文本都被赋予一个 Enum。 Enum 类有一个返回字符串的方法,该方法检查正在使用的语言环境,并在运行时从翻译集合中选择正确的翻译。
这具有双重用途 - 您可以从 IDE 中完成代码,并且永远不要忘记翻译字符串。
用法非常简单,举个例子几乎是多余的,但这里是如何使用translation-enum
System.out.println(Translations.GREET_PERSON.trans()+" "+user.getName());
或者,如果你想花哨的话,让 Enum 接受参数,通过一些神奇的字符串操作,这些参数将插入到翻译字符串中的标记位置
System.out.println(Translations.GREET_PERSON.trans(user.getName());
【讨论】:
我不太确定问题的标题与其余部分的位置相符。是的,Java 枚举有行为。他们也可以有状态,虽然它应该真的,真的是不可变的状态。 (可变枚举值的想法在 IMO 中非常可怕。)
基本上,Java 中的枚举是一组固定的对象。好处是您知道如果您有该类型的引用,它总是要么是null,要么是众所周知的集合之一。
就我个人而言,我真的很喜欢 Java 枚举,并希望 C# 也有它们 - 它们比 C# 的枚举(基本上是“命名数字”)更面向对象。在初始化顺序方面有一些“陷阱”,但它们通常都很棒。
【讨论】: