Search code examples
javacloneprivate-memberseffective-java

Effective Java: clone() private access


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?


Solution

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