为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

明月笑刀无情 2019-10-15 15:43:44
如何在Java中创建不可变对象?哪些对象应称为不可变的?如果我的所有静态成员都上课,这是不可变的吗?
查看完整描述

3 回答

?
慕的地10843

TA贡献1785条经验 获得超8个赞

以下是不可变对象的严格要求。


最终上课

使所有成员成为最终成员,在静态块或构造函数中显式设置它们

将所有成员设为私人

否修改状态的方法

要特别注意限制对可变成员的访问(请记住,该字段可能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 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;  

    }


}

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


要解决的问题是,要坚决保证不变性,您必须将类标记为final。这在Joshua Bloch的Effective Java中进行了深入介绍,并在Java内存模型规范中明确引用。


查看完整回答
反对 回复 2019-10-15
?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

要使类在Java中不可变,可以注意以下几点: 


1.不要提供setter方法来修改该类的任何实例变量的值。


2.将课程声明为“最终”。这将防止任何其他类对其进行扩展,从而阻止其覆盖任何可能修改实例变量值的方法。


3.将实例变量声明为private和final。


4.您还可以将类的构造函数声明为私有,并在需要时添加工厂方法来创建类的实例。



这些要点应该有帮助!!


查看完整回答
反对 回复 2019-10-15
  • 3 回答
  • 0 关注
  • 564 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信