In Bloch's Effective Java, 2nd edition, Item 11: Override clone judiciously has the following example:
class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
this.elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}
// Ensure space for at least one more element.
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
@Override public Stack clone() {
try {
Stack result = (Stack) super.clone();
result.elements = elements.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
As you can see, in the clone()
method, a new object of type Stack
is created, called result
. We subsequently clone result.elements
, despite the fact that the Stack
class defines elements
as a private member. What's going on and why is it permitted?
A private
member is only visible from other members in the same class, not especially in the same instance.
EDIT :
down vote The private modifier enforces Encapsulation principle.
Here is a quote from a similar question about C# but the principle is the same.
The
private
modifier enforces Encapsulation principle.The idea is that 'outer world' should not make changes to AClass internal processes because AClass implementation may change over time (and you would have to change the whole outer world to fix the differences in implementation - which is nearly to impossible).
When instance of AClass accesses internals of other AClass instance - you can be sure that both instances always know the details of implementation of AClass. If the logic of internal to AClass processes is changed - all you have to do is change the code of AClass.
Furthermore is allows to override equals()
or compareTo()
without having to expose the attributes involved in their evaluation.