简体   繁体   中英

Creating an immutable object without final fields?

Can we create an immutable object without having all fields final?

If possible a couple of examples would be helpful.

Declare all fields private and only define getters:

public final class Private{
    private int a;
    private int b;

    public int getA(){return this.a;}
    public int getB(){return this.b;}
}

citing @Jon Skeet's comment, final class modifier is useful for:

While an instance of just Private is immutable, an instance of a subclass may well be mutable. So code receiving a reference of type Private can't rely on it being immutable without checking that it's an instance of just Private.

So if you want to be sure the instance you are referring to is immutable you should use also final class modifier.

Yes, it is - just make sure that your state is private, and nothing in your class mutates it:

public final class Foo
{
    private int x;

    public Foo(int x)
    {
        this.x = x;
    }

    public int getX()
    {
        return x;
    }
}

There's no way of mutating the state within this class, and because it's final you know that no subclasses will add mutable state.

However:

  • The assignment of non-final fields doesn't have quite the same memory visibility rules as final fields, so it might be possible to observe the object "changing" from a different thread. See section 17.5 of the JLS for more details on the guarantees for final fields.
  • If you're not planning on changing the field value, I would personally make it final to document that decision and to avoid accidentally adding a mutating method later
  • I can't remember offhand whether the JVM prevents mutating final fields via reflection; obviously any caller with sufficient privileges could make the x field accessible in the above code, and mutate it with reflection. (According to comments it can be done with final fields, but the results can be unpredictable.)

The term "immutable", when used to descrbie Java objects, should mean thread-safe immutability. If an object is immutable, it is generally understood that any thread must observe the same state.

Single thread immutability is not really interesting. If that is what really referred to, it should be fully qualified with "single thread"; a better term would be "unmodifiable".

The problem is to give an official reference to this strict usage of the term 'immutable'. I can't; it is based on how Java bigshots use the term. Whenever they say "immutable object", they are always talking about thread safe immutable objects.

The idiomatic way to implement immutable objects is to use final fields; final semantics was specifically upgraded to support immutable objects. It is a very strong guarantee; as a matter of fact, final fields is the only way; volatile fields or even synchronized block cannot prevent an object reference from being published before constructor is finished.

是的,如果您创建的对象只包含私有成员并且没有提供setter,那么它将是不可变的。

I believe the answer is yes.

consider the following object:

public class point{
   private int x; 
   private int y;
   public point(int x, int y)
   {
      this.x =x; 
      this.y =y;
    }

   public int getX()
    {
       return x;
    }

    public int getY()
    { 
        return y;
    }

}

This object is immutable.

A class is immutable if it does not provide any methods that are accessible from the outside that modify the state of the object. So yes, you can create a class that is immutable without making the fields final. Example:

public final class Example {
    private int value;

    public Example(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

However, there is no need to do this in real programs, and it is recommended to always make fields final if your class should be immutable.

Yes. Make the fields private. Don't change them in any methods other than the constructor. Of course, that being the case, why wouldn't you label them as final???

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM