如何在 Java 中创建不可变对象? [英] How to create immutable objects in Java?

查看:29
本文介绍了如何在 Java 中创建不可变对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 Java 中创建不可变对象?

How to create immutable objects in Java?

哪些对象应该被称为不可变的?

Which objects should be called immutable?

如果我有一个包含所有静态成员的类,它是不可变的吗?

If I have class with all static members is it immutable?

推荐答案

以下是不可变对象的硬性要求.

Below are the hard requirements of an immutable object.

  1. 完成课程
  2. 使所有成员成为最终成员,并设置他们显式地,在静态块中,或在构造函数中
  3. 将所有成员设为私有
  4. 没有修改状态的方法
  5. 要非常小心地限制对可变成员的访问(记住字段可能是final,但对象仍然可以是可变的.即private final Date imStillMutable).在这些情况下,您应该制作防御性副本.
  1. Make the class final
  2. make all members final, set them explicitly, in a static block, or in the constructor
  3. Make all members private
  4. No Methods that modify state
  5. Be extremely careful to limit access to mutable members(remember the field may be final but the object can still be mutable. ie private final Date imStillMutable). You should make defensive copies in these cases.

创建 final 类背后的原因非常微妙,经常被忽视.如果它不是最终的人可以自由扩展您的类,覆盖 publicprotected 行为,添加可变属性,然后提供它们的子类作为替代.通过声明 final 类,您可以确保这不会发生.

The reasoning behind making the class final is very subtle and often overlooked. If its not final people can freely extend your class, override public or protected behavior, add mutable properties, then supply their subclass as a substitute. By declaring the class final you can ensure this won't happen.

要查看实际问题,请考虑以下示例:

To see the problem in action consider the example below:

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 instances
of 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;  
    }

}

在实践中,在依赖注入环境中遇到上述问题是很常见的.您没有显式实例化事物,并且您获得的超类引用实际上可能是一个子类.

In practice it is very common to encounter the above problem in Dependency Injection environments. You are not explicitly instantiating things and the super class reference you are given may actually be a subclass.

需要注意的是,要对不变性做出硬保证,您必须将类标记为 final.Joshua Bloch 的 Effective Java 和在 Java 内存模型的规范中明确引用了一>.

The take away is that to make hard guarantees about immutability you have to mark the class as final. This is covered in depth in Joshua Bloch's Effective Java and referenced explicitly in the specification for the Java memory model.

这篇关于如何在 Java 中创建不可变对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆