使用简单 XML 框架反序列化不可变 class

Deserialize immutable class with Simple XML framework

假设我有一个 class 这样的:

public class Measurement {
    /** The date and time at which the measurement was taken. */
    public final Date date;

    /** The measurement value. */
    public final float value;

    /** The name of the engineer who took the measurement. */
    public final String engineer;

    public Measurement(Date date, float value, String engineer) {
        super();
        this.date = date;
        this.value = value;
        this.engineer = engineer;
    }
}

每个 Measurement 实例都是不可变的。一旦创建,其成员将无法修改。但是,可以创建一个新实例,其中一些值是从现有实例复制而来的,另一些设置不同。

如果事情变得更复杂,例如因为有大量的字段,而且其中大部分都不是强制性的,所以构造函数将是私有的,而 class 将伴随着一个构建器 class 。 (事实上​​ ,实际代码更复杂;这只是一个最小的例子。)

现在我可以很容易地添加一些简单的XML注释来将其序列化为XML,像这样:

@Root(name="measurement")
@Default
public class Measurement {
    /** The date and time at which the measurement was taken. */
    @Attribute
    public final Date date;

    /** The measurement value. */
    @Attribute
    public final float value;

    /** The name of the engineer who took the measurement. */
    @Attribute
    public final String engineer;

    public Measurement(Date date, float value, String engineer) {
        super();
        this.date = date;
        this.value = value;
        this.engineer = engineer;
    }
}

这将序列化为如下内容:

<measurement date="2019-11-01 11:55:42.0 CET" value="42.0" engineer="Doe"/>

然后我如何将生成的 XML 代码反序列化回 class?

官方的做法似乎是constructor injection:设置最终成员的唯一方法是通过构造函数,并且构造函数对每个成员都有一个参数。所以构造函数看起来像这样:

public Measurement(@Attribute(name="date") Date date,
                   @Attribute(name="value") float value,
                   @Attribute(name="engineer") String engineer) {
    super();
    this.date = date;
    this.value = value;
    this.engineer = engineer;
}

据我所知,这里需要指定属性名称,即使它对应于参数。

在示例中,构造函数是 public。不确定这里需要什么,因为 SimpleXML 似乎依赖于反射来找到正确的构造函数。