Java 枚举相对于旧的“类型安全枚举”的优点图案?
在 JDK1.5 之前的 Java 中,“Typesafe Enum”模式是实现只能采用有限数量值的类型的常用方法:(
public class Suit {
private final String name;
public static final Suit CLUBS =new Suit("clubs");
public static final Suit DIAMONDS =new Suit("diamonds");
public static final Suit HEARTS =new Suit("hearts");
public static final Suit SPADES =new Suit("spades");
private Suit(String name){
this.name =name;
}
public String toString(){
return name;
}
}
参见 Bloch 的 Effective Java 中的 Item 21)。
现在在JDK1.5+中,“官方”的方式显然是使用enum
:
public enum Suit {
CLUBS("clubs"), DIAMONDS("diamonds"), HEARTS("hearts"), SPADES("spades");
private final String name;
private Suit(String name) {
this.name = name;
}
}
显然,语法更好,更简洁(不需要为值显式定义字段,适合>toString()
提供),但到目前为止,enum
看起来非常像 Typesafe Enum 模式。
我知道的其他差异:
- 枚举自动提供
values()
方法 - 枚举可以在
switch()
中使用(编译器甚至会检查您是否忘记了但这
一切看起来只不过是语法糖而已,甚至还存在一些限制(例如 enum
总是继承自 java.lang.Enum
,并且不能被子类化)。
enum
提供的其他更基本的好处是否是 Typesafe Enum 模式无法实现的?
In Java prior to JDK1.5, the "Typesafe Enum" pattern was the usual way to implement a type that can only take a finite number of values:
public class Suit {
private final String name;
public static final Suit CLUBS =new Suit("clubs");
public static final Suit DIAMONDS =new Suit("diamonds");
public static final Suit HEARTS =new Suit("hearts");
public static final Suit SPADES =new Suit("spades");
private Suit(String name){
this.name =name;
}
public String toString(){
return name;
}
}
(see e.g. Item 21 from Bloch's Effective Java).
Now in JDK1.5+, the "official" way is obviously to use enum
:
public enum Suit {
CLUBS("clubs"), DIAMONDS("diamonds"), HEARTS("hearts"), SPADES("spades");
private final String name;
private Suit(String name) {
this.name = name;
}
}
Obviously, the syntax is a bit nicer and more concise (no need to explicitly define fields for the values, suitable toString()
provided), but so far enum
looks very much like the Typesafe Enum pattern.
Other differences I am aware of:
- enums automatically provide a
values()
method - enums can be used in
switch()
(and the compiler even checks that you don't forget a value)
But this all looks like little more than syntactic sugar, with even a few limitations thrown in (e.g. enum
always inherits from java.lang.Enum
, and cannot be subclassed).
Are there other, more fundamental benefits that enum
provides that could not be realized with the Typesafe Enum pattern?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
enum
中定义的一组值,仅此而已!enum
正确处理序列化。您也可以使用类型安全枚举来做到这一点,但它经常被忘记(或根本不知道)。这可确保对于任意两个enum
值,e1.equals(e2)
始终 意味着e1 == e2
>e1
和e2
(反之亦然,这可能更重要)。EnumSet
和EnumMap
(从这个答案)enum
and no more!enum
correctly handles serialization. You can do that with type-safe enums as well, but it's often forgotten (or simply not known). This ensures thate1.equals(e2)
always impliese1 == e2
for any twoenum
valuese1
ande2
(and vice versa, which is probably more important).EnumSet
andEnumMap
(stolen from this answer)当然,还有很多其他人会在这里提到的优点作为答案。最重要的是,您可以非常快地编写
枚举
,并且它们可以执行很多操作,例如实现Serialized
、Comparable
、equals()< /code>、
toString()
、hashCode()
等,您没有将其包含在枚举中。但我可以向您展示
enum
的严重缺点(IMO)。您不仅不能随意对它们进行子类化,而且不能为它们配备通用参数。当你可以这样写时:这对于枚举来说是不可能的:
Of course there are lots of advantages other people will mention here as answers. Most importantly, you can write
enums
very fast and they do a lot of things like implementSerializable
,Comparable
,equals()
,toString()
,hashCode()
, etc, which you didn't include in your enum.But I can show you a serious drawback of
enum
(IMO). Not only can't you subclass them at will, but you can't equip them with a generic parameter. When you could write this:This is not possible with an enum:
实际上,这更像是
因为枚举已经提供了
name()
方法。此外,它们还提供了ordinal()方法(该方法支持高效的数据结构,如EnumSet和EnumMap),实现Serialized >,覆盖toString
,提供values()
和valueOf(String name)
。它们可以用在类型安全的 switch 语句中,并且是单例。Actually, it's more like
because enums already provide a
name()
method. Additionally, they provide anordinal()
method (which enables efficient data structures likeEnumSet
andEnumMap
), implementSerializable
, overridetoString
, providevalues()
andvalueOf(String name)
. They can be used in a type safe switch statement, and are singletons.您的类型安全枚举实现有点过于简单化。当你处理序列化时,它会变得更加复杂。
Java
enum
通过序列化/反序列化来解决问题。enum
保证是唯一的,您可以将它们与==
运算符进行比较。阅读《Effective Java 第二版》中的相应章节(关于使用枚举而不是单例,关于使用
EnumSet
等)。Your type-safe enum implementation is a bit oversimplified. When you deal with serialization it will become much more complicated.
Java
enum
s solve the problem with serialization/deserialization.enum
's are guarantied to be unique and you can compare them with==
operator.Read correspondent chapters in Effective Java 2nd Edition (about using enums instead of singletons, about using
EnumSet
s etc).EnumSet
和EnumMap
是围绕枚举的特定功能构建的自定义数据结构。它们具有方便的额外功能,而且速度非常快。如果没有枚举,就没有与它们等效的东西(至少没有同等优雅的使用,请参阅注释)。EnumSet
andEnumMap
are custom data structures that are built around the specific features of enums. They have handy extra features and they are extremely fast. There is no equivalent (at least not with equivalent elegance of use, see comments) to them without enums.另外:
JDK5枚举可以很容易地在switch-case语句中使用,并且具有良好的IDE支持
In addition:
JDK5 enums can be easily used in switch-case statements with good IDE support
语法糖本身就有价值 :-P 毕竟, ( : ) 也是如此。
但说真的,事实上,自动开箱即用的 name() 和 ordinal() 、枚举它们、在 switch () 中使用它们、为它们附加附加值对它们来说是很好的论据:它避免了很多样板代码。
传统的惰性替代方案(使用整数)不是类型安全的,而且受到更多限制。
与此替代方案相比,枚举的缺点是它们不再是轻量级的。
Syntactic sugar alone is worth its salt :-P After all, that's what for ( : ) is, too.
But seriously, the fact to have automatically name() and ordinal() out of the box, to enumerate them, to use them in switch (), to attach additional values to them are good arguments for them: it avoids lot of boilerplate code.
The traditional lazy alternative, using ints, isn't typesafe and is much more limited.
A drawback of enums over this alternative is that they are no longer lightweight.