Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encapsulation for mutable objects in Java

I was studying the "Java SE 7 Programmer I & II Study Guide" and I did not understand the explanation below.

class Fortress{
  private String name;
  private ArrayList<Integer> list;

  Fortress() {list=new ArrayList<Integer>;

  String getName{return name;}
  void addToList(int x){list.add(x);}
  ArrayList getList(){return list;} // line 1
}

Which lines of code break encapsulation? Answer: line 9. "When encapsulating a mutable object like an ArrayList, your getter must return a reference to a copy of the object, not just the reference to the original object".

I did not either understand the explanation or how to modifiy the original code.

So in the getList() instead of

return list;

Should we do this?

ArrayList<Integer> list2=list;
return list2;
like image 368
sevenxuguang Avatar asked Dec 29 '15 01:12

sevenxuguang


People also ask

What is mutable object in Java?

A mutable object can be changed after it's created, and an immutable object can't. In Java, everything (except for strings) is mutable by default: public class IntegerPair { int x; int y; IntegerPair(int x, int y) { this.

How can we create immutable class if there is some mutable object in class?

To create a custom immutable class we have to do the following steps. Declare the class as final so it can't be extended. Make all fields private so that direct access is not allowed. Do not provide setter methods (methods that modify fields) for variables, so that it can not be set.

Can you create an immutable object that contains a mutable object in Java?

If you want to encapsulate a mutable object into an immutable one, then you need to: Create a copy of the mutable object (i.e. via copy constructor, cloning, serialization/deserialization, etc.); never store the reference to the original mutable object. Never return the mutable object.


2 Answers

You would have replace:

return list;

with:

return new ArrayList<Integer>(list);

Otherwise the client can do...

foo.getList().add(5);

breaking encapsulation.

like image 55
Pace Avatar answered Oct 02 '22 05:10

Pace


we do this?

ArrayList<Integer> list2=list;
return list2;

No, it says a copy of the object, not a copy of the reference.

ArrayList<Integer> list2= new ArrayList<>();
list2.addAll( list );
return list2;

Or as pointed out, ArrayList has a copy constructor that will add all elements from another list to the new list. The above three lines are intended primarily to be clear what is being done.

like image 30
markspace Avatar answered Oct 02 '22 07:10

markspace