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

时间:2014-02-18 14:52:22

标签: java xjc wsimport

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

问题:

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

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

1 个答案:

答案 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编写扩展名以使其按照您的意愿执行。甚至可能存在现有的扩展。我不知道。