如果它有一个java.lang.Object的实例变量,我如何创建一个类Immutable?

时间:2011-08-19 18:57:54

标签: java immutability

final public class ImmutableWithObject {

    final Object obj;
    final List myList;

    ImmutableWithObject(Object obj1, List list)
    {
        this.obj = obj1;
        this.myList = ((List) ((ArrayList) list).clone());
    }

    public Object getObj() {
        return this.obj;
    }

    public List getMyList() {
        return (List) ((ArrayList<String>) this.myList).clone();
    }

    public static void main(String[] args) {

        ImmutableWithObject io = new ImmutableWithObject(new Date(), new ArrayList());

        ((Date) io.getObj()).setDate(22);

        System.out.println((Date) io.getObj());
    }
}
o/p : Mon Aug 22 00:50:04 IST 2011

这是不正确的。

4 个答案:

答案 0 :(得分:6)

不可变意味着一旦构造了对象,其状态就不会改变。

  • 让课程决赛(你已经完成)
  • 将实例变量设为私有和最终
  • 不提供改变状态的方法
  • 传递实例变量时,请发送副本而不是原始副本。

来自EJ第15项&lt; - 更多信息

除非有充分的理由让它们变得可变,否则类应该是不可变的。如果一个类不能成为不可变的,尽可能地限制它的可变性。

答案 1 :(得分:2)

您不能使其不可变,因为此对象无法创建列表或Object的内容的副本。假设您想要访问这些属性的getter,属性本身是在别处创建的,并且可以在此类的外部代码中更改,该类具有对它的引用。

唯一的例外是Object和List的内容本身是不可变的。然后,您可以创建列表的不可变副本,您将完成。

答案 2 :(得分:1)

您可以复制List对象的值。无论谁调用它仍然具有该列表并且可以修改它。

答案 3 :(得分:0)

将成员变量设为private final并复制参数:

final class ImmutableWithObject {

    private final Object obj;
    private final List myList;

    public ImmutableWithObject(Object obj1 , List list)
    {
       this.obj = obj1.clone();
       this.list = (List) list.clone();
    }
}

这不允许任何其他类更改您的内部状态,也不允许ImmutableWithobject更改myListobj引用。 然而 obj的状态以及列表仍然可以在内部操作。正如其他人所指出的那样,无论谁通过名单或obj1到你的班级,也能够从外部操纵它。由于在C ++中没有类似const的东西,我们必须复制对象以确保它们不会从外部更改。

同样,如果有一个getter,它也应该只返回一个副本(或一些只读接口或只读包装器):

 public Object getObj() { return obj.clone(); }