为什么 Java 枚举不可克隆?
现在改变问题已经太晚了,但更准确的是问“为什么clone()不允许单例?”。 copy()
方法会更方便。
Java 中的枚举不能被克隆有什么原因吗?
该手册指出
这保证了枚举永远不会被克隆,这是保持其“单例”状态所必需的。
但是返回实例本身也将保留其状态,并且我将能够像其他可克隆对象一样处理关联的枚举。
有人可能会争辩说
[clone()] 的一般意图是,对于任何对象 x,表达式:
x.clone() != x
将为 true,[...]
但对于单例,相反,我希望 x.clone() == x
为 true 。如果返回实例本身,那么单例模式对于引用对象来说将是透明的。
那么,为什么在指定 clone()
时,枚举不允许被克隆,或者他们忘记考虑单例和不可变呢?
It's too late to change the question, but more precise would have been to ask "Why does clone() not allow singletons?". A copy()
method would be more convenient.
Is there any reason why enums in Java cannot be cloned?
The manual states that
This guarantees that enums are never cloned, which is necessary to preserve their "singleton" status.
But returning the instance itself would also preserve its status, and I would be able to handle associated enums the same way as other clonable objects.
One may argue that
The general intent [of clone()] is that, for any object x, the expression:
x.clone() != x
will be true, [...]
But for singletons on the contrary I want x.clone() == x
to be true. If the instance itself would be returned, then the singleton pattern would be transparent to referencing objects.
So why are enums not allowed to be cloned or did they forget to think about singletons and immutables, when clone()
was specified?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果 x.clone() == x ,克隆单例的目的是什么?你不能直接使用
x
吗?严格来说,如果您想克隆某些东西并强制
x.clone() == x
,则唯一可以作为克隆结果的对象是x
本身:这可能会产生误导...
如果您正在设计某些东西并基于
clone()
进行区分,那么恕我直言,您做错了...What's the purpose of cloning a singleton, if
x.clone() == x
? Can't you just usex
straight away.Strictly speaking, if you want to clone something and enforce
x.clone() == x
, the only object that can be the result of the clone isx
itself:Which can be misleading...
If you are designing something and are based on
clone()
for differentiation, you are doing it wrong IMHO...如果您的克隆方法返回
this
实例而不是一个不同的对象,那么它就不是克隆,不是吗?Javadoc 说:
枚举不应该被克隆,因为每个值应该只有一个实例。
编辑:回应以下评论:
因为这确实没有意义。如果它是同一个对象,那么它就不是克隆。 Javadoc 还说:
因此,clone() 方法的目的是返回一个不同的对象。不幸的是,它说这不是绝对的要求,这使得您的建议有效,但我仍然认为这是不明智的,因为有一个返回
this
的克隆方法没有用。如果您正在做一些可疑的事情(例如在枚举常量中具有可变状态或对其进行同步),它甚至可能会导致问题。此类代码的行为会有所不同,具体取决于克隆方法是否进行了正确的克隆或仅返回this
。当枚举本质上不可克隆时,您并没有真正解释为什么要将它们视为可克隆的。想要有一个不遵守公认约定的克隆方法似乎是为了解决您的方法中一些更基本的问题。
If your clone method returns
this
instance rather than a distinct object, then it's not a clone, is it?The Javadoc says:
Enums are not supposed to be cloned because there is supposed to only ever be one instance of each value.
EDIT: In response to the following comment:
Because it doesn't really make sense. If it's the same object then it's not a clone. The Javadocs also say:
So the intent is for the
clone()
method to return a distinct object. Unfortunately it says that it's not an absolute requirement, which makes your suggestion valid, but I still think it's not sensible because it's not useful to have a clone method that returnsthis
. It might even cause problems if you were doing something dubious like having mutable state in your enum constants or synchronising on them. The behaviour of such code would be different depending on whether the clone method did proper cloning or just returnedthis
.You don't really explain why you want to treat enums as
Cloneable
when they are inherently un-cloneable. Wanting to have a clone method that doesn't obey the accepted conventions seems like a hack to solve some more fundamental problem with your approach.你可能想要,但我认为下面的代码会中断很奇怪:(
当然,因为
clone()
只提供浅拷贝,即使是它的正确实现可能会导致上述代码中的错误。)另一方面,我可以同意克隆操作对于不可变对象仅
返回 this
是有意义的,并且枚举确实应该是不可变的。现在,当编写clone()
的合约时,他们显然没有考虑不可变性,或者他们不想要语言不支持的概念的特殊情况(即不可变)类型)。所以,
clone()
就是它的本质,你不能很好地去改变自 Java 1.0 以来就存在的东西。我非常确定在某个地方,有一些代码完全依赖于clone()
返回一个新的、不同的对象,也许作为IdentityHashMap
或其他内容。You may want to, but I think it's weird that the following code would break:
(Of course, since
clone()
only gives shallow copies, even a correct implementation of it may cause errors in the above code.)On the other hand, I can sort of agree that it would make sense for cloning operations to just
return this
for immutable objects, and enums really should be immutable. Now, when the contract forclone()
was written, they apparently didn't think about immutables, or they didn't want a special case for a concept that's not supported by the language (i.e., immutable types).And so,
clone()
is what it is, and you can't very well go and change something that's been around since Java 1.0. I'm quite certain that somewhere out there, there is code that totally relies onclone()
returning a new, distinct object, perhaps as a key for anIdentityHashMap
or something.我猜他们不想在指定
clone()
时将单例视为特殊情况。这会使规范变得复杂。因此,现在库开发人员必须将它们视为特殊情况,但对于我们其他人来说,很高兴我们可以信任x.clone() != x
。I guess they didn't want to treat singletons as a special case when
clone()
was specified. That would have complicated the specification. So now the library developers have to treat them as a special case, but for the rest of us, it's nice that we can trust thatx.clone() != x
.你自己对你的问题的回答就是最好的答案。一般来说,人们期望clone()返回一个不同的对象。这样一来,
Cloneable
本身的语义就更有意义了。 (“该对象是可克隆的......哦,我必须能够复制。”)我无法立即想到这很重要的情况,但这就是Cloneable
的预期语义含义。我认为即使他们考虑单身,他们也不会改变它。毕竟,程序员有责任通过有选择地添加(并可能覆盖)
Cloneable
接口来决定什么可以克隆、什么不能克隆,并且大多数程序员不会添加也可以是单例的可克隆接口。
Your own answer to your question is the best one. In general, people expect
clone()
to give back a different object. The semantics ofCloneable
itself make more sense that way. ("The object is cloneable...oh, I must be able to make copies.") I can't think of a situation offhand where that matters, but that was the intended semantic meaning ofCloneable
.I think that even if they were thinking about singletons, they would not have changed it. After all, it's the programmer's responsibility to decide what can be cloned and what can't, by selectively adding (and potentially overriding) the
Cloneable
interface, and most programmers are not going to add theCloneable
interface to singletons either.不,那不会是克隆人。所以,对于单身人士,你想要这样:
No, that wouldn't be a clone. So, for singletons, you want this: