我想知道为什么生成(来自xsd)列表的getter始终为null检查:
public class Response {
@XmlElement(type = Integer.class)
protected List<Integer> integers;
public List<Integer> getIntegers() {
if (integers == null) {
integers = new ArrayList<Integer>();
}
return this.integers;
}
}
Run Code Online (Sandbox Code Playgroud)
题:
为什么?是什么原因?有什么好的吗?
我问在某些情况下,这不是一件好事.看起来没有办法改变这种行为.
经过一番挖掘后,原因就变得清晰了.我xjc为list属性生成了一些代码,它创建了这个注释:
/**
* Gets the value of the bars property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the bars property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getBars().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Bar }
*
*
*/
Run Code Online (Sandbox Code Playgroud)
这使他们的意图明确.他们希望它不可能List从对象中过时,因此它总是返回实时列表而不是复制.这意味着对getter的多次调用(例如,来自不同的线程或不同的上下文)将始终被赋予对相同的内存中对象的引用.但是,这样做意味着他们不能拥有一个setter,或者他们违反了这个合同 - Context A可以设置该值,然后Context B将对旧值进行陈旧引用,并且无法知道它已被改变.
因为,由于这个设计决定,他们不能有一个setter,如果你需要添加或删除项目,需要有一些方法来改变列表.否则,最初的null列表将永远是null永远的(禁止带有反射的恶作剧).因此,允许的唯一剩余方法是null在getter中检查,并在那时进行惰性初始化.这意味着必须采用替换整个清单的方案
foo.getBars().clear();
foo.getBars().addAll(someList);
Run Code Online (Sandbox Code Playgroud)
至于为什么选这个设计...有没有办法让那支球队之外任何人都知道这个问题的答案.但是,对于大多数代码来说,它通常都是一个非常好的模式(它减少了耦合,并消除了编译器无法警告你的常见错误条件),因此很难对其进行大量论证.如果它真的给你带来了麻烦(而且你还没有真正展示它是什么,除了你的一些对象在复制操作后有空列表而不是空列表的事实),那么我能给你的唯一建议是要么不使用代码生成器,要么编写扩展名xjc以使其按照您的意愿执行.甚至可能存在现有的扩展.我不知道.
| 归档时间: |
|
| 查看次数: |
507 次 |
| 最近记录: |