慕的地10843
以下是不可变对象的严格要求。最终上课使所有成员成为最终成员,在静态块或构造函数中显式设置它们将所有成员设为私人否修改状态的方法要特别注意限制对可变成员的访问(请记住,该字段可能final是可变的,但对象仍然可以是可变的。即private final Date imStillMutable)。defensive copies在这种情况下,您应该这样做。上课的final原因很微妙,常常被忽略。如果不是最终的人,他们可以自由地扩展您的类,覆盖public或protected行为,添加可变属性,然后提供其子类作为替代。通过声明该类,final您可以确保不会发生这种情况。要查看实际问题,请考虑以下示例:public class MyApp{ /** * @param args */ public static void main(String[] args){ System.out.println("Hello World!"); OhNoMutable mutable = new OhNoMutable(1, 2); ImSoImmutable immutable = mutable; /* * Ahhhh Prints out 3 just like I always wanted * and I can rely on this super immutable class * never changing. So its thread safe and perfect */ System.out.println(immutable.add()); /* Some sneak programmer changes a mutable field on the subclass */ mutable.field3=4; /* * Ahhh let me just print my immutable * reference again because I can trust it * so much. * */ System.out.println(immutable.add()); /* Why is this buggy piece of crap printing 7 and not 3 It couldn't have changed its IMMUTABLE!!!! */ }}/* This class adheres to all the principles of * good immutable classes. All the members are private final* the add() method doesn't modify any state. This class is * just a thing of beauty. Its only missing one thing* I didn't declare the class final. Let the chaos ensue*/ public class ImSoImmutable{ private final int field1; private final int field2; public ImSoImmutable(int field1, int field2){ this.field1 = field1; this.field2 = field2; } public int add(){ return field1+field2; }}/*This class is the problem. The problem is the overridden method add(). Because it uses a mutable member it means that I can't guarantee that all instancesof ImSoImmutable are actually immutable.*/ public class OhNoMutable extends ImSoImmutable{ public int field3 = 0; public OhNoMutable(int field1, int field2){ super(field1, field2); } public int add(){ return super.add()+field3; }}实际上,在依赖注入环境中遇到上述问题是很常见的。您没有显式实例化事物,并且给出的超类引用实际上可能是子类。要解决的问题是,要坚决保证不变性,您必须将类标记为final。这在Joshua Bloch的Effective Java中进行了深入介绍,并在Java内存模型规范中明确引用。