Reputation: 6364
I was implementing an immutable class whose structure is as below :
public final class A{
private final B bOb;
public A(){
bOb = new B();
}
public A(A a){
bOb = new B(a.bOb);
}
public A addData(Type data){ // Type - Integer,String,char,etc.
A newA = new A(this); //making a copy of the object that is calling addData method
newA.bOb.add(data);
return newA;
}
}
Is this implementation correct ? Let's say the object bOb is a list.
Upvotes: 3
Views: 244
Reputation: 4289
Your implementation:
public A addData(int data){
A newA = new A(this);
newA.bOb.add(data); // <--- bOb is mutable
return newA;
}
A bOb is being changed, so if you expose any direct access to bOb, it can be changed. (Since you're not exposing anything about bOb, the scenario doesn't make sense.)
Hints:
Collections.emptyList()
returns an immutable list.Collections.unmodifiableList()
returns an immutable shallow-copy of a given list.Consider this "safer" implementation:
import java.util.*;
public final class A<T>{ //T must also be immutable (String, integer, char, ...)
private final List<T> list;
public A(){
this.list = Collections.emptyList();
}
public A(List<T> list){
this.list = Collections.unmodifiableList(list);
}
public A<T> addData(T data){
List<T> shallowCopy = new ArrayList<T>(this.list);
shallowCopy.add(data);
return new A<T>(shallowCopy);
}
public List<T> getItems() {
return this.list;
}
}
Upvotes: 2
Reputation: 24676
It depends on how B(B b)
constructor works. If it is a copy constructor, it should make a deep copy of b
fields. In this case A
is immutable.
Instead if the constructor simply take the reference to the same b
instance, any change to it will reflect on bOb
property, so the A
class in not immutable...
Upvotes: 0
Reputation: 106351
It is not totally immutable, since B appears to be mutable itself (via the add method) and A contains an instance of B.
However I think it is effectively immutable (i.e. it behaves as if it was immutable from the perspective of an external observer) providing that all the following are true:
new B(B)
performs a complete deep copy of B
(if not then addData
may mutate something within the original B
)bOb
via any other meansYou get most of the benefits of immutability from being effectively immutable so I think this design is OK providing Type
is immutable - it's fine to mutate an object during it's construction providing it never gets mutated after you pass a reference to someone else. A good example of this is java.lang.String
- internally it contains a mutable array that is written to while the String is constructed but never changed after that point.
Upvotes: 2
Reputation: 33019
In this form, yes, your class is immutable.
However, this is a trivial example and wouldn't actually be useful for anything since you can't access any of the internal data. The thing you need to be careful of is to not let any references to bOb
escape from A
. If you add a method which returns bOb
, you need to return a copy of bOb
to avoid accidentally allowing the caller to mutate any of the contents of A
.
Upvotes: 1
Reputation: 2474
If bOb
is a list and it contains mutable content, then not. But it seems that you use only int
as content and this solves the problem.
Upvotes: 1