我想知道为什么生成(来自xsd)getter for list始终为null check:
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;
}
}
问题:
为什么呢?是什么原因?有什么好的吗?
我问,在某些情况下,这不是一件好事。看起来没有办法改变这种行为。
答案 0 :(得分:5)
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 }
*
*
*/
这使他们的意图明确。他们希望从对象中获取陈旧的List
是不可能的,因此它总是返回实时列表而不是复制。这意味着对getter的多次调用(例如,来自不同的线程或不同的上下文)将始终被赋予对相同的内存中对象的引用。但是,这样做意味着他们不能拥有一个setter,或者他们违反了这个合同 - Context A可以设置该值,然后Context B将对旧值进行陈旧引用,并且无法知道它已经改变了。
由于那个设计决定,他们没有一个setter,如果你需要添加或删除项目,需要有一些方法来改变列表。否则,最初的null
列表将始终为null
(禁止使用反射的恶作剧)。因此,允许的唯一剩余方法是在getter中检查null
,并在那时进行延迟初始化。这意味着替换整个列表的方案必须是
foo.getBars().clear();
foo.getBars().addAll(someList);
至于为什么他们选择了这个设计......那个团队以外的任何人都无法知道答案。但是,对于大多数代码来说,它通常都是一个非常好的模式(它减少了耦合,并消除了编译器无法警告你的常见错误条件),因此很难对其进行大量论证。如果它真的给你带来了麻烦(而且你还没有真正展示它是什么,除了你的一些对象在复制操作后有空列表而不是空列表的事实),那么我能给你的唯一建议是要么不使用代码生成器,要么为xjc
编写扩展名以使其按照您的意愿执行。甚至可能存在现有的扩展。我不知道。