wsimport(xjc) - 为什么列表getter总是空检查?

Hub*_*ert 0 java xjc wsimport

我想知道为什么生成(来自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)

题:

为什么?是什么原因?有什么好的吗?

我问在某些情况下,这不是一件好事.看起来没有办法改变这种行为.

Ian*_*ird 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 }
 * 
 * 
 */
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以使其按照您的意愿执行.甚至可能存在现有的扩展.我不知道.