How to create immutable objects in Java?

How to create immutable objects in Java?

What objects should be called immutable?

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

+79
java immutability
Jun 10 '11 at 11:32
source share
14 answers

The following are the stringent requirements of an immutable object.

  1. Make a class finale
  2. make all members final, set them explicitly, in a static block or in a constructor
  3. Make all members private
  4. There are no methods that change state
  5. Be extremely careful to limit access to mutable elements (remember that a field can be final but an object can still be mutable. private final Date imStillMutable ). You must make defensive copies in these cases.

The reasons for making the final class very subtle and are often overlooked. If non-final users can freely extend your class, override public or protected behavior, add mutable properties, and then provide your subclass as a replacement. By declaring a final class, you can be sure that this will not 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, the above problem is very common in dependency injection environments. You are not creating explicit instances, and the superclass reference you give may actually be a subclass.

The conclusion is that in order to get solid guarantees of immutability, you must mark the class as final . This is discussed in detail in Joshua Bloch Effective Java and is explicitly mentioned in the Java memory model specification.

+79
Jun 10 '11 at 11:33
source share

Classes are not immutable, there are objects.

Immutable means: my public visible state cannot change after initialization.

Fields do not have to be declared final, although this can significantly help ensure thread safety.

If a class has only static members, the objects of this class are immutable, because you cannot change the state of this object (you probably cannot create it :))

+13
Jun 10 2018-11-11T00:
source share

Just don't add public mutator (setter) methods to the class.

+12
Jun 10 2018-11-11T00:
source share

To make a class immutable in Java, you can consider the following points:

1. Do not provide customization methods to change the values ​​of any of the class instance variables. 2. Declare the class as 'final' . This would prevent the spread of any other class and, therefore, the exclusion from it of any method that could change the values ​​of instance variables. 3. Declare instance variables as private and final .

4. You can also declare the class constructor as private and add a factory method to instantiate the class if necessary.

These points should help!

+6
Dec 31 '13 at 14:27
source share

To create an immutable class, you need to follow these steps:

 Declare the class as final so it can't be extended. Make all fields private so that direct access is not allowed. Don't provide setter methods for variables Make all mutable fields final so that it's value can be assigned only once. Initialize all the fields via a constructor performing deep copy. Perform cloning of objects in the getter methods to return a copy rather than returning the actual object reference. 
+3
Jan 07 '16 at 7:29
source share

From oracle site, how to create immutable objects in Java.

  • Do not provide setter methods - methods that modify fields or objects referenced by fields.
  • Make all fields final and private.
  • Do not let subclasses override methods. The easiest way to do this is to declare the class final. A more complex approach is to make the constructor private and build instances in factory methods.
  • If links to mutable objects are included in the instance fields, do not allow these objects to be modified:
    I. Do not provide methods that modify mutable objects.
    II. Do not use references to mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies and store links to copies. In the same way, create copies of your internal mutable objects, if necessary, to avoid the originals returning to your methods.
+3
Jun 21 '16 at 3:16
source share

First of all, you know why you need to create an immutable object and what are the advantages of an immutable object.

The advantages of an immutable object

Concurrency and multithreading This is automatically Thread-safe, so the synchronization problem ... etc.

No need to copy constructor. No clone implementation required . The class cannot be overridden Make the field private and final Force calls to create an object completely in one step, instead of using the no-Argument constructor

Immutable objects are simply objects whose state means that the data of the object cannot change after the immutable object is built.

see below code.

 public final class ImmutableReminder{ private final Date remindingDate; public ImmutableReminder (Date remindingDate) { if(remindingDate.getTime() < System.currentTimeMillis()){ throw new IllegalArgumentException("Can not set reminder" + " for past time: " + remindingDate); } this.remindingDate = new Date(remindingDate.getTime()); } public Date getRemindingDate() { return (Date) remindingDate.clone(); } } 
+2
Jan 03
source share
  • Do not provide "setter" methods - methods that modify fields or objects referenced by fields.
  • Make all fields final and private.
  • Do not let subclasses override methods. The easiest way to do this is to declare the class final. A more complex approach is to make the constructor private and build instances in factory methods.
  • If instance fields include references to mutable objects, do not allow these objects to be modified:
    • Do not provide methods that modify mutable objects.
    • Do not use references to mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies and store links to copies. In the same way, create copies of your internal mutable objects, if necessary, to avoid the originals returning to your methods.
+2
Jun 11 '15 at 16:34
source share

Minimize variability

An immutable class is simply a class whose instances cannot be changed. All information contained in each copy is provided during its creation and is recorded for the lifetime of the object.

JDK immutable classes: String, boxed classes (wrapper classes), BigInteger and BigDecimal, etc.

How to make a class immutable?

  • Do not provide any methods that change the state of objects (known as mutators).
  • Make sure the class cannot be extended.
  • Make all fields final.
  • Make all fields private. This prevents clients from accessing the mutable objects referenced by the fields and directly modifying these objects.
  • Make protective copies. Provide exclusive access to any mutable components.

    public List getList () {return Collections.unmodifiableList (list); <=== protective copy of mutable before returning it to the caller}

If your class has fields related to mutable objects, make sure that class clients cannot get references to these objects. Never initialize such a field for a reference to an object provided by the client, or never return a reference to an object from an accessor.

 import java.util.Date; public final class ImmutableClass { public ImmutableClass(int id, String name, Date doj) { this.id = id; this.name = name; this.doj = doj; } private final int id; private final String name; private final Date doj; public int getId() { return id; } public String getName() { return name; } /** * Date class is mutable so we need a little care here. * We should not return the reference of original instance variable. * Instead a new Date object, with content copied to it, should be returned. * */ public Date getDoj() { return new Date(doj.getTime()); // For mutable fields } } import java.util.Date; public class TestImmutable { public static void main(String[] args) { String name = "raj"; int id = 1; Date doj = new Date(); ImmutableClass class1 = new ImmutableClass(id, name, doj); ImmutableClass class2 = new ImmutableClass(id, name, doj); // every time will get a new reference for same object. Modification in reference will not affect the immutability because it is temporary reference. Date date = class1.getDoj(); date.setTime(date.getTime()+122435); System.out.println(class1.getDoj()==class2.getDoj()); } } 

For more information, see my blog:
http://javaexplorer03.blogspot.in/2015/07/minimize-mutability.html

+2
Dec 24 '16 at 4:11
source share

an object is called immutable if its state cannot be changed after its creation. One of the easiest ways to create an immutable class in Java is that all its fields are final. If you need to write an immutable class that includes mutable classes such as "java.util.Date". To preserve immutability in such cases, it is advised to return a copy of the original object,

+1
Jul 31 '13 at 4:57
source share

Immutable objects are those objects whose state cannot be changed after they are created, for example, the String class is an immutable class. Immutable objects cannot be modified, so they can also be thread safe when executed at the same time.

Features of immutable classes:

  • just build
  • automatic streaming security
  • a good candidate for map keys and Set, since their internal state has not changed during processing
  • no clone implementation is required, as they always represent the same state.

Keys for writing an immutable class:

  • make sure the class cannot be overridden.
  • make all member variables private and final
  • don't give your customization methods
  • reference to the object should not leak during the construction phase
+1
Oct 23 '13 at 18:48
source share

The next few steps should be considered if you want a class to be an immutable class.

  • The class must be marked final
  • All fields must be closed and trailing.
  • Replace setters with a constructor (to assign a value to a variable).

Let's take a look at what we typed above:

 //ImmutableClass package younus.attari; public final class ImmutableExample { private final String name; private final String address; public ImmutableExample(String name,String address){ this.name=name; this.address=address; } public String getName() { return name; } public String getAddress() { return address; } } //MainClass from where an ImmutableClass will be called package younus.attari; public class MainClass { public static void main(String[] args) { ImmutableExample example=new ImmutableExample("Muhammed", "Hyderabad"); System.out.println(example.getName()); } } 
+1
Jan 17 '14 at 7:30
source share

Usually ignored but important properties of immutable objects

In addition to the answer provided by @ nsfyn55, the following aspects of immutability of objects that are of primary importance should be considered

Consider the following classes:

 public final class ImmutableClass { private final MutableClass mc; public ImmutableClass(MutableClass mc) { this.mc = mc; } public MutableClass getMutClass() { return this.mc; } } public class MutableClass { private String name; public String getName() { return this.name; } public void setName(String name) { this.name = name; } } public class MutabilityCheck { public static void main(String[] args) { MutableClass mc = new MutableClass(); mc.setName("Foo"); ImmutableClass iMC = new ImmutableClass(mc); System.out.println(iMC.getMutClass().getName()); mc.setName("Bar"); System.out.println(iMC.getMutClass().getName()); } } 

Below will be a conclusion from MutabilityCheck:

  Foo Bar 

It is important to note that

  1. Building mutable objects on an immutable object (via the constructor) by "copying" or "closing" the variables of an instance of an immutable object described by the following changes:

     public final class ImmutableClass { private final MutableClass mc; public ImmutableClass(MutableClass mc) { this.mc = new MutableClass(mc); } public MutableClass getMutClass() { return this.mc; } } public class MutableClass { private String name; public MutableClass() { } //copy constructor public MutableClass(MutableClass mc) { this.name = mc.getName(); } public String getName() { return this.name; } public void setName(String name) { this.name = name; } } 

still does not guarantee complete immutability, since the following is still valid from the MutabilityCheck class:

  iMC.getMutClass().setName("Blaa"); 
  1. However, starting MutabilityCheck with the changes made to 1. will lead to the conclusion:

     Foo Foo 
  2. To achieve complete immutability of an object, all its dependent objects must also be immutable.

0
Jul 26 '18 at 2:02
source share

An immutable object is an object that does not change its internal state after creation. They are very useful in multi-threaded applications because they can be shared between threads without synchronization.

To create an immutable object, you must follow a few simple rules:

1. Do not add installation method

If you build an immutable object, its internal state will never change. The goal of the setter method is to change the internal value of the field so that you cannot add it.

2. Declare all fields as final and closed.

A closed field is not visible outside the class, so no manual changes can be applied to it.

Declaring a final field ensures that if it refers to a primitive value, the value will never change; if it refers to an object, the link cannot be changed. This is not enough to guarantee that an object with only private trailing fields is not mutable.

3. If the field is a mutable object, create protective copies of it for receiving methods

We saw earlier that defining a final and private field is not enough, because you can change its internal state. To solve this problem, we need to create a protective copy of this field and return this field each time it is requested.

4. If the mutable object passed to the constructor should be assigned to the field, create a protective copy of it

The same problem arises if you hold the link passed to the constructor because it can be changed. Thus, keeping a reference to the object passed to the constructor, you can create mutable objects. To solve this problem, it is necessary to create a protective copy of the parameter if they are mutable objects.

Please note that if the field is a reference to an immutable object, there is no need to create its protective copies in the constructor and in the methods of obtaining, it is enough to define the field as final and closed.

5. Do not let subclasses override methods

If a subclass overrides a method, it can return the original value of the field being changed instead of its protective copy.

To resolve this problem, you can do one of the following:

  1. Declare the immutable class as final so that it cannot be extended
  2. Declare all methods of the immutable class final so that they cannot be overridden
  3. Create a private constructor and factory to instantiate an immutable class, because a class with private constructors cannot be extended

If you follow these simple rules, you can freely share your immutable objects between threads, because they are thread safe!

Below are a few more points of variability / immutability:

  • Immutable objects really make life easier in many cases. They are especially applicable for value types where objects do not have an identity, so they can be easily replaced and they can make parallel programming safer and cleaner (most notoriously difficult to detect concurrency errors are ultimately caused by a mutable state shared between threads). However, for large and / or complex objects, creating a new copy of the object for each individual change can be very expensive and / or tedious . And for objects with an individual identity, changing existing objects is much simpler and more intuitive than creating a new modified copy.
  • There are some things that you simply cannot do with immutable objects, such as having a bi-directional relationship . Once you set the association value for one object, its identity changes. So, you are setting a new value for another object, and it is also changing. The problem is that the first reference to the object is no longer valid because a new instance was created to represent the object with the link. Continuation of this will lead to endless regressions.
  • To implement a binary search tree , you must return a new tree each time: your new tree will have to make a copy of each changed node (unchanged branches are shared). For your insert function, this is not so bad, but for me it all became pretty inefficient when I started working on removal and rebalancing.
  • Hibernate and JPA essentially dictate that your system uses mutable objects because their whole premise is that they detect and save changes to your data objects.
  • Depending on the language, the compiler can do a bunch of optimizations when working with immutable data, because it knows that the data will never change. All kinds of things are skipped, giving you a huge performance boost.
  • If you look at other well-known JVM languages ​​( Scala, Clojure ), mutable objects are rarely found in code, and therefore people start using them in scripts where single-threaded is not enough.

There is no right or wrong, it just depends on what you prefer. It depends only on your preferences and what you want to achieve (and the ability to easily use both approaches without pushing the unwavering fans of either side is the holy grail that some languages ​​strive for).

0
Jan 27 '19 at 20:23
source share



All Articles