Java 关于不可变类

Java 关于不可变类,java,Java,我有下面的查询,我正在研究Java不可变类的概念,并得出以下分析 所有字段必须是私有字段,最好是最终字段 确保类不能被重写-使类成为最终类,或者使用静态工厂并保持构造函数私有 必须从构造函数/工厂填充字段 不要为字段提供任何设置器 注意收藏。使用集合。不可修改*。 此外,集合应仅包含不可变对象 所有getter必须提供不可变对象或使用防御性复制 不要提供任何更改对象内部状态的方法。 现在我有下面的课 public final class Bill { private final int

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

所有字段必须是私有字段,最好是最终字段 确保类不能被重写-使类成为最终类,或者使用静态工厂并保持构造函数私有 必须从构造函数/工厂填充字段 不要为字段提供任何设置器 注意收藏。使用集合。不可修改*。 此外,集合应仅包含不可变对象 所有getter必须提供不可变对象或使用防御性复制 不要提供任何更改对象内部状态的方法。 现在我有下面的课

public final class Bill {

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

}

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

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

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

由于int是一个原语,并且来自JodaTime的DataTime是不可变的,因此我猜它是不可变的,您只需确保使用不可变列表:

public final class Bill {
    ...
    public Bill(int amount, DateTime dateTime, List<Integer> orders) {
        this.amount = amount;
        this.dateTime = dateTime;
        this.orders = Collections.unmodifiableList(orders);
    }
    ...
}
显然,您还需要一个构造函数来初始化最终字段和一些访问这些字段的方法。

由于int是一个原语,而来自JodaTime的DataTime是不可变的,我想您只需要确保使用不可变列表:

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

显然,您还需要一个构造函数来初始化最终字段和一些访问这些字段的方法。

您的类是不可变的。现在,您可能需要添加一些方法:

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.unmodifiableListorders;并从getOrders返回它:return orders;,这强制了这样一个事实,即即使在您的类中,也不应该修改该列表。

您的类是不可变的。现在,您可能需要添加一些方法:

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.unmodifiableListorders;并从getOrders返回它:return orders;,它强制您即使在类中也不应修改该列表。

并不是所有这些都是技术上必需的-例如,String.hashCode是延迟计算的,其hashCode字段不是最终字段,但是字符串被认为是不可变的。>它的hashCode字段不是final,这就是为什么提到字段最好是final。只要它们由于对象的外部消息而不可修改,成员就可以是非最终成员,对吗?并非所有这些都是技术要求的-例如,String.hashCode是延迟计算的,其hashCode字段不是最终字段,但是字符串被认为是不可变的。>它的hashCode字段不是final,这就是为什么提到字段最好是final。只要它们由于对象的外部消息而不可修改,成员就可以是非最终成员,对吗?