Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Immutable Objects [closed]

I am learning the concept of immutability.

I understand that immutable objects cannot change their values once the object is created.

But I didn't understand the following uses of immutable objects.

They are

  • are automatically thread-safe and have no synchronization issues. How ? Proof ?
  • do not need a copy constructor. How ? Any example ?
  • do not need an implementation of clone How ? Any example ?
  • do not need to be copied defensively when used as a field How ? Any example ?
  • always have "failure atomicity" (a term used by Joshua Bloch) : if an immutable object throws an exception, it's never left in an undesirable or indeterminate state. How ? Any example ?

Could someone please explain each of these points in detail with examples supporting it ?

Thanks.

like image 598
tmgr Avatar asked Jul 18 '13 08:07

tmgr


People also ask

Do all properties of immutable objects need to be final?

No, it is not mandatory to have all properties final to create an immutable object. In immutable objects you should not allow users to modify the variables of the class. You can do this just by making variables private and not providing setter methods to modify them.

Can we break immutable class in Java?

More detailed answer: Yes serialization can break immutability. It looks great. It's immutable (you can't change start and end after initialization), elegant, small, threadsafe etc. You have to remember that serialization is another way of creating objects (and it is not using constructors).

What is immutable objects in Java?

An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code. Immutable objects are particularly useful in concurrent applications.

What is the benefit of using immutable objects in Java?

The advantage of immutable objects is that you know their data cannot change, so you don't have to worry about that. You can pass them around freely without having to remember whether a method you pass them to could change them in a way your code is not prepared to handle. That makes working with immutable data easier.


2 Answers

..are automatically thread-safe and have no synchronization issues

Concurrency problems happen when two different threads modify the state of the same object. Immutable objects can't be modified, so no problems.

Example: A String. Two threads can be passed the same String without worry since neither can mutate it in any way.

do not need a copy constructor

... because copy is the only way to mutate it. One common design pattern for immutable objects for every "modification" operation to make a copy and then perform the operation on the new object.

Copy constructors are usually used on objects that you want to change without affecting the original. This is always the case (by definition) with immutable objects.

In the case of String, all the methods and the + operator return new Strings.

do not need an implementation of clone

see above.

do not need to be copied defensively when used as a field

Once upon a time I did something silly. I had a set of enums in a List:

private static final List<Status> validStatuses;

static {
  validStatuses = new ArrayList<Status>();
  validStates.add(Status.OPEN);
  validStates.add(Status.REOPENED);
  validStates.add(Status.CLOSED);
}

This list was returned from a method:

public static List<Status> getAllStatuses() {
  return validStates;
}

I retrieved that list but only wanted to show the open states in the interface:

List<Status> statuses = Status.getAllStatuses();
statuses.remove(Status.CLOSED);

Great, it worked! Wait, now all status lists are showing only those two -- even after page refresh! What happened? I modified a static object. Oops.

I could have used defensive copying on the return object of getAllStatuses. Or, I could use something like Guava's ImmutableList in the first place:

private static final List<Status> validStatuses =
    ImmutableList.of(Status.OPEN, Status.REOPENED, Status.CLOSED);

Then when I did something dumb:

List<Status> statuses = Status.getAllStatuses();
statuses.remove(Status.CLOSED);  // Exception!

always have "failure atomicity" (a term used by Joshua Bloch) : if an immutable object throws an exception, it's never left in an undesirable or indeterminate state.

Because the class can never be modified, all states emitted by modification are whole, qualified objects (because they cannot change, they must always be in a qualified state to be useful). An exception would not emit a new object and therefore you can never have an undesirable or indeterminate state.

like image 158
Nicole Avatar answered Sep 28 '22 02:09

Nicole


They are automatically thread-safe and have no synchronization issues

Yes due to the guarantees provided by the Java Memory Model for final fields:

final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads.

do not need to be copied defensively when used as a field How ? Any example ?

Because they are immutable, they can't be modified, so it is fine to share them with external code (you know they won't be able to mess up with the state of the object).

Corollary: you don't need to copy / clone immutable objects.

always have "failure atomicity"

An immutable object does not change once it is properly constructed. So either construction fails and you get an exception or it does not and you know the object is in a consistent state.

like image 33
assylias Avatar answered Sep 28 '22 00:09

assylias