5
final public class ImmutableWithObject {

    final Object obj;
    final List myList;

    ImmutableWithObject(Object obj1, List list)
    {
        this.obj = obj1;
        this.myList = ((List) ((ArrayList) list).clone());
    }

    public Object getObj() {
        return this.obj;
    }

    public List getMyList() {
        return (List) ((ArrayList<String>) this.myList).clone();
    }

    public static void main(String[] args) {

        ImmutableWithObject io = new ImmutableWithObject(new Date(), new ArrayList());

        ((Date) io.getObj()).setDate(22);

        System.out.println((Date) io.getObj());
    }
}
o/p : Mon Aug 22 00:50:04 IST 2011

which is incorrect.

3
  • Do you intend to expose the Object after creation? (ie, a getObj() method?) Commented Aug 19, 2011 at 19:06
  • 1
    Please elaborate a bit on your question so it is clear what you really want to prevent (protection of internal state, information hidding, encapsulation). Commented Aug 19, 2011 at 19:19
  • I've posted the whole code . now the question is to make this class immutable Commented Aug 19, 2011 at 19:41

4 Answers 4

6

Immutable means that once the object has been constructed, its state does not change.

  • Make class final ( which you have already done )
  • Make the instance variables as private and final
  • Dont provide methods that change the state
  • When passing instance variables, send copies instead of original.

From EJ Item 15 <-- Lot more information in there

Classes should be immutable unless there's a very good reason to make them mutable. If a class cannot be made immutable, limit its mutability as much as possible.

Sign up to request clarification or add additional context in comments.

12 Comments

Common sense should be applied instead.
If the class is final, then private and final won't make a difference (as long as they are not public). To make it immutable, you have to only accept immutable classes as parameters to the constructor, or copy them in the constructor. If mutable classes are passed in there is no way to guarantee immutability.
@Robin -- if the fields are protected or package-private, then other classes in the same package can obtain a reference to it and modify it. Its necessary to mark them as final also because otherwise you could have trouble when passing objects between threads without synchronization.
Robin you are correct , but there should be some generic way to make a copy of Object type.
@Robin, not true. If the private field will be used by multiple threads, then some sort of concurrency visibility mechanism must be used. Making a field final allows all threads to see the same state. Other choices are synchronize and volatile.
|
2

You cannot make it immutable since this object cannot create copies of the contents of the list or the Object. Assuming that you mean to have getters for accessing those properties, the properties themselves were created elsewhere and can be changed in code external to this class that has a reference to it.

The only exception to this is if the contents of Object and List are themselves immutable. Then you can create an immutable copy of the list and you would be done.

Comments

1

You can make a copy of the values of the List object. Whoever called it still has that List and can modify it.

Comments

1

Make the member variables private final and copy the parameters:

final class ImmutableWithObject {

    private final Object obj;
    private final List myList;

    public ImmutableWithObject(Object obj1 , List list)
    {
       this.obj = obj1.clone();
       this.list = (List) list.clone();
    }
}

This will not allow any other class to change your internal state and will not allow ImmutableWithobject to change the myList or obj references. However the obj's state as well as the list can still be manipulated internally. As others pointed out, whoever past the list or obj1 to you class, would be able to manipulate it from the outside too. Since there is no equivalent of something like const in C++, we will have to copy the objects to make sure they are not changed from the outside.

Similarly, if there was a getter, it should also only return a copy (or some read-only interface or a read-only wrapper):

 public Object getObj() { return obj.clone(); }

14 Comments

However, that does not make the List immutable.
first thing the problem in this is when this object is instantiated at that time you could use java.util.Date as object.
This adds nothing to the defined class with respect to mutability since there is no way of changing those properties anyway.
There is no way to make the List instance immutable anyway (obj neither). However, I changed the access modifiers so at least it cannot be changed externally and the interface can ensure immutability.
@Robin: Ok, I see what the original poster might be looking for now.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.