1

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

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

现在我有以下课程..

public final class Bill {

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

}

请告知如何将其制成不可变类。

4

3 回答 3

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;,这强制您不应该修改该列表,即使在您的类中也是如此。

于 2012-08-09T16:43:09.780 回答
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字段和一些可以访问该字段的方法。

于 2012-08-09T16:42:38.430 回答
0

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

于 2012-08-09T16:42:23.413 回答