Java Immutable Objects [closed]
Asked Answered
G

4

6

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.

Groan answered 18/7, 2013 at 8:19 Comment(4)
I've voted to close. This is five questions combined in one, each of which will require broad detailed answers. Not sure why this has three up-votes.Visitor
Is this some kind of homework? Also please note that there are many questions at once and also some questions are opinion based. Please make your question more concrete and show us what you have tried.Shiv
This smells a litte bit like homework - you may ask questions which are to the point, and not that general. Go and try to solve these questions on your own first - if you are stuck, we might helpTrumaine
These are not homework! I stuck at this site javapractices.com/topic/TopicAction.do?Id=29Groan
W
10

..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.

Westbrook answered 18/7, 2013 at 8:26 Comment(0)
P
2

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.

Papillary answered 18/7, 2013 at 8:27 Comment(3)
But String are immutable object by default, but still we make String fields inside class of immutable object as "final" ? Why ?Groan
For an object to be immutable, all its fields must be final (apart from limited and complex exceptions). So if your object contains a string field, it must be marked as final. Otherwise, you lose the thread safety guarantee, even if the string can't be modified. See also, for more details: #16061530Papillary
@tm99 If you don't mark a String field as final, you won't lose thread-safety on the String itself (which is immutable). You lose it on the object that has a String field, which is not final!Gassy
W
1

It's not a concept that can be usefully explained with examples of it. The advantage of immutable objects is that you know their data cannot change, so you don't have to worry about that. You can use your immutable object freely without having fear that the method in which you are passing them will change it.

when we are performing a multithreaded program than this comes handy because bugs based on the data changed by the threads is not supposed to be done

Winonawinonah answered 18/7, 2013 at 8:42 Comment(0)
L
0

Automatically thread safe

  • because they cannot be changed (cannot mutate) - any thread accessing it finds the object in same state. So there are no situations like one thread changes state of object, then second thread takes over and changes state of object, then again first one takes over with no clue, that it was changed by someone else
  • good example is ArrayList - if one thread iterates through its' elements and second thread removes some of them, first thread then throws some kind of concurrency exception. With immutable list this is prevented

Copy constructor

  • it does not mean that it cannot have a copy constructor. It is a constructor to which you pass object of same type, and you create new object as a copy of given object. It is only a guess, but why would you copy object that is always in a same state?
public class A
{
    private int a;

    public A(int a)
    {
        this.a = a;
    }

    public A(A original)
    {
        this.a = original.a;
    }

}  

Implementation of clone

  • same issue, cloning object, that is always in same state usually only takes space in memory. But you can do it, if you want to create mutable object out of immutable
  • good example are again collections, you can generate mutable collection out of immutable

Defensive copying

  • defensive copy means, that when you are setting an object to a field, you create new object of same type which is copy of the original
  • Example
Leibniz answered 18/7, 2013 at 8:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.