在 Setter 中复制列表会使 XML Unmarshaller 无法工作

Copying List in Setter makes XML Unmarshaller not work

我有一个这样的 DataBean:

@XmlRootElement
public class DataBean {
    private List<String> data;

    @XmlElement(name = "data")
    public List<String> getData() {
        return data != null ? Collections.unmodifiableList(data) : null;
    }

    public void setData(List<String> data) {
        data = new ArrayList<>(data);
        data.sort(Comparator.naturalOrder());
        this.data = data;
    }
}

在DataBean 内部,列表必须排序,否则DataBean 在我的域中不可用。为了避免副作用,我复制了setter中的列表,然后对它进行排序。

编组此 bean 工作正常,但在解组时,数据列表为空(非空)。下面是一些代码来演示:

public class XmlTester {

    public static void main(String[] args) {
        List<String> data = Arrays.asList("one", "two", "three", "four");
        DataBean dataBean = new DataBean();
        dataBean.setData(data);
        System.out.printf("Data in original bean: %s%n%n", dataBean.getData().toString());

        try {
            String xmlString = serialize(dataBean);
            System.out.printf("XML:%n%s%n", xmlString);
            DataBean deserializedDataBean = deserialize(xmlString);
            System.out.printf("Data in deserialized bean: %s%n%n", deserializedDataBean.getData().toString());
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    private static String serialize(DataBean dataBean) throws JAXBException {
        StringWriter w = new StringWriter();
        JAXBContext jc = JAXBContext.newInstance(DataBean.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(dataBean, w);
        return w.toString();
    }

    private static DataBean deserialize(String xmlString) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(DataBean.class);
        Unmarshaller um = context.createUnmarshaller();
        return (DataBean) um.unmarshal(new StringReader(xmlString));
    }
}

这会产生以下输出:

Data in original bean: [four, one, three, two]

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dataBean>
    <data>four</data>
    <data>one</data>
    <data>three</data>
    <data>two</data>
</dataBean>

Data in deserialized bean: []

如果我从 bean 中的 setter 中删除行 data = new ArrayList<>(data);,解组就像一个魅力,所以复制操作似乎是问题所在。

为什么复制使反序列化bean中的列表为空,我可以在不删除复制操作的情况下解决这个问题吗?

当然,我可以改为测试数据是否已排序,如果未排序则抛出 IllegalArgumentException,但我更愿意在 setter.

中对副本进行排序
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class DataBean {


    @XmlElement(name = "data")
    private List<String> data;

    public List<String> getData() {
        return data != null ? Collections.unmodifiableList(data) : null;
    }

    public void setData(List<String> data) {
        data = new ArrayList<>(data);
        data.sort(Comparator.naturalOrder());
        this.data = data;
    }
}
Data in original bean: [four, one, three, two]

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dataBean>
    <data>four</data>
    <data>one</data>
    <data>three</data>
    <data>two</data>
</dataBean>

Data in deserialized bean: [four, one, three, two]