日历的防御性副本

JJ *_*ter 17 java calendar defensive-copy

一直试图找到实现制作Calendar对象防御性副本的方法的最佳方法.

例如:

public void setDate(Calendar date) {
    // What to do.... 
}
Run Code Online (Sandbox Code Playgroud)

我特别关注在检查空输入和制作副本时是否存在线程交错,还是我错过了一些非常明显的东西?

Jon*_*eet 26

(针对现在略有不同的观众,我猜......)

我会使用,clone()如果我绝对不得不使用Calendar(而不是Joda时间).你在评论中争辩说你担心"顽皮的子类" - 你会如何建议在任何方案中解决这个问题?如果您对所涉及的子类一无所知,并且不信任它们,那么您无法保留特定于类型的数据.如果你不相信子类不要搞砸了,你通常会遇到更大的问题.在执行日期/时间计算时,您如何相信它能为您提供正确的结果?

clone()是克隆对象的预期方式:它是我期望一个合理的子类挂钩它所需的任何类型特定行为的地方.您不需要知道哪些状态位是相关的 - 您只需让类型处理它本身.

Calendar.getInstance()自己使用和设置属性的好处:

  • 您将保留相同的日历类型
  • 您不必担心忘记属性:这是该类型的责任
  • 你明确地说什么你想做的事,并让执行照顾的如何,这总是好的.您的代码完全表达了您的意图.

编辑:就原始问题所担心的"线程交错"而言:date参数的值不会改变其他线程所做的任何事情.但是,如果当你需要一个防守副本,另一个线程变异的对象的内容,这可能很容易引起问题.如果这是一个风险,那么基本上你就会遇到更大的问题.


Luk*_*pec 16

最简单的方法是:

copy = Calendar.getInstance(original.getTimeZone());
copy.setTime(original.getTime());
Run Code Online (Sandbox Code Playgroud)

但我强烈建议(尽可能)使用JodaTime来表达Java中的时间和日期.它具有不可变类和可变类.

  • @zeller你对时区是正确的.我编辑了这个例子. (3认同)
  • 我认为这不会确保日历将在同一时区. (2认同)