java.util.Date 克隆或复制以不公开内部引用

发布于 2024-11-30 01:11:57 字数 314 浏览 1 评论 0原文

最好不要公开对象(实体)的内部引用。因此,如果一个对象有一个 java.util.Date 类型的字段,那么该字段的 getter 应该返回的不是原始日期,而是它的副本。

util.Date 有两种常见的方法来创建该副本:

  • clone: (Date) originalDate.clone()
  • 通过构造函数复制 new Date(originalDate.getTime())

My问题是,哪种方式更好,并且 为什么?

It is best practice not to expose the internal references of an Object (Entity). So if an Object has a field of type java.util.Date then for example the getter for this field should return not the original date but an copy of it.

But for an java.util.Date there are two common ways to create that copy:

  • clone: (Date) originalDate.clone()
  • copy via constructor new Date(originalDate.getTime())

My question is, which way is better, and why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

じ违心 2024-12-07 01:11:57

如果它绝对只是一个Date,那么无论哪种方式都没有任何区别。

如果实际对象可能是 Date 的子类(例如 java.sql.Date),那么我希望克隆() 将保留额外信息(包括它是哪个类),而调用构造函数则不会。

顺便说一句,如果你使用 Joda Time 你就不会遇到这个问题,因为有很多不可变类型可以使用。这也是一个更好的 API :)

If it's definitely just a Date, it won't make any difference either way.

If the actual object might be a subclass of Date (such as java.sql.Date) then I'd hope that clone() would preserve the extra information (including which class it is) whereas calling the constructor wouldn't.

As an aside, if you used Joda Time you wouldn't have this problem, as there are plenty of immutable types to use. It's also a much better API :)

微凉 2024-12-07 01:11:57

阅读Effective Java。创建副本的首选方法是使用复制构造函数方法。

Bill Venners:在您的书中,您建议使用复制构造函数
而不是实现 Cloneable 并编写克隆。您可以...吗
详细说明一下吗?

乔什·布洛赫(Josh Bloch):如果您读过我书中有关克隆的内容,
尤其是如果你读到字里行间,你就会知道我认为
克隆被深深地破坏了。有一些设计缺陷,最大的
也就是说Cloneable接口没有clone方法。
这意味着它根本不起作用:使某些东西可克隆
没有说明你可以用它做什么。相反,它说
关于它内部可以做什么。它说如果通过调用
super.clone 重复它最终会调用Object的clone方法,this
方法将返回原始的字段副本。

Read Effective Java. The preferred way to create copies is to use the copy constructor approach.

Bill Venners: In your book you recommend using a copy constructor
instead of implementing Cloneable and writing clone. Could you
elaborate on that?

Josh Bloch: If you've read the item about cloning in my book,
especially if you read between the lines, you will know that I think
clone is deeply broken. There are a few design flaws, the biggest of
which is that the Cloneable interface does not have a clone method.
And that means it simply doesn't work: making something Cloneable
doesn't say anything about what you can do with it. Instead, it says
something about what it can do internally. It says that if by calling
super.clone repeatedly it ends up calling Object's clone method, this
method will return a field copy of the original.

梦里兽 2024-12-07 01:11:57

如果您进行防御性编码,则需要复制构造函数。请参阅来自Effective Java 的这段文字

另请注意,我们没有使用 Date 的克隆方法来制作防御性副本。因为 Date 是非final的,所以clone方法不能保证返回一个类为java.util.Date的对象;它可能会返回专门为恶意恶作剧而设计的不受信任子类的实例。例如,这样的子类可以在创建时在私有静态列表中记录对每个实例的引用,并允许攻击者访问该列表。这将使攻击者可以自由控制所有实例。为了防止此类攻击,请勿使用克隆方法为其类型可被不受信任方子类化的参数创建防御性副本。

If you're coding defensively, you'll want the copy constructor. See this passage from Effective Java:

Note also that we did not use Date's clone method to make the defensive copies. Because Date is nonfinal, the clone method is not guaranteed to return an object whose class is java.util.Date; it could return an instance of an untrusted subclass specifically designed for malicious mischief. Such a subclass could, for example, record a reference to each instance in a private static list at the time of its creation and allow the attacker access to this list. This would give the attacker free reign over all instances. To prevent this sort of attack, do not use the clone method to make a defensive copy of a parameter whose type is subclassable by untrusted parties.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文