关于不可变类

时间:2012-08-09 16:36:07

标签: java

我有以下查询,我正在通过Java不可变类概念并提出以下分析..

  • 所有字段必须是私有的,最好是最终字段
  • 确保无法覆盖类 - 使类最终,或使用静态工厂并使构造函数保持私有
  • 必须从“构造函数/工厂”
  • 填充字段
  • 不要为字段提供任何设置器
  • 留意收藏品。使用Collections.unmodifiable *。
  • 此外,集合应仅包含不可变对象
  • 所有获取者必须提供不可变对象或使用防御性复制
  • 不提供任何更改对象内部状态的方法。

现在我有以下课程。

public final class Bill {

    private final int amount;
    private final DateTime dateTime;
    private final List<Integers> orders;

}

请告知如何将其作为不可变类。

3 个答案:

答案 0 :(得分:6)

你的课程是不可改变的。现在您可能想要添加一些方法:

public final class Bill {

    private final int amount;
    private final DateTime dateTime;
    private final List<Integers> orders;

    public Bill(int amount, DateTime dateTime, List<Integer> orders) {
        this.amount = amount; //primitive type: ok
        this.dateTime = dateTime; //joda.DateTime is immutable: ok
        this.orders = new ArrayList<Integer> (orders); //make a copy as the caller could modify the list at its end
    }

    // no method that adds or removes from the list

   public List<Integer> getOrders() {
       return Collections.unmodifiableList(orders); //defensive copy
   }
}

或者,您可以在构造函数中使用this.orders = Collections.unmodifiableList(orders);并从getOrders()返回它:return orders;,这会强制您不应修改该列表,即使在您的类中也是如此。

答案 1 :(得分:3)

由于int是一个原语,DataTime(来自JodaTime,我猜)是不可变的,你唯一需要做的就是确保使用不可变列表:

public final class Bill {
    ...
    public Bill(int amount, DateTime dateTime, List<Integer> orders) {
        this.amount = amount;
        this.dateTime = dateTime;
        this.orders = Collections.unmodifiableList(orders);
    }
    ...
}

显然,您还需要一个构造函数来初始化final字段以及一些可以访问这些字段的方法。

答案 2 :(得分:0)

由于amount是值类型,datetime是不可修改的,如果在其getter中返回orders属性的Collections.unmodifiable()版本,该类将变为不可变。