2012-08-09 19 views
1

我有以下查询,我会通过Java不变类的概念,并提出了如下分析..对于不可改变的类

  • 所有字段必须是私有的,最好最后
  • 确保类不能被覆盖 - 使课堂最后,或者使用静态工厂,并保持建设者私人
  • 字段必须从构造/工厂进行填充
  • 不要为字段提供任何setter方法
  • 注意收藏。使用Collections.unmodifiable *。
  • 此外,收藏应该只包含一个不可改变的对象
  • 所有干将必须提供不可变对象或使用保护性拷贝
  • 不提供改变对象的内部状态的任何方法。

现在我有下面的类..

public final class Bill { 

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

} 

请告知如何将它做成不可变类。

+2

并非所有这些技术上都是必需的 - 例如,'String.hashCode()'是懒散计算的,它的'hashCode'字段不是最终的,但是'String'即使如此也被认为是不可变的。 – 2012-08-09 16:40:55

+0

>其hashCode字段不是最终的 这就是为什么提到这些字段是最好是最终的。只要它们不能通过外部消息传递给对象来修改,那么这些成员就不是最终的,对吗? – Vikdor 2012-08-09 16:46:55

回答

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;,这就加强了事实,你不应该修改该列表中,即使在你的班。

0

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

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字段以及一些访问该字段的方法。