Эффективная Java: частный доступ clone()

В книге Блоха «Эффективная Java», 2-е издание, Пункт 11: Разумное переопределение клона содержит следующий пример:

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();
        }
    }
}

Как видите, в методе clone() создается новый объект типа Stack с именем result. Впоследствии мы клонируем result.elements, несмотря на то, что класс Stack определяет elements как закрытый член. Что происходит и почему это разрешено?


person Abhishek Divekar    schedule 22.06.2017    source источник
comment
@JEY Спасибо. Не могли бы вы аргументировать, почему это разрешено?   -  person Abhishek Divekar    schedule 22.06.2017
comment
вы документацию читали?   -  person JEY    schedule 22.06.2017
comment
@JEY да, я сделал. Вы прочитали мой вопрос? В нем говорится о доступе к закрытым членам разных экземпляров одного и того же класса, что разрешает Java. Я хотел бы знать, почему. В приведенном вами примере речь идет о доступе к закрытым членам в разных классах, что не разрешено.   -  person Abhishek Divekar    schedule 22.06.2017
comment
Возможно, stackoverflow.com/questions/1548879/   -  person    schedule 22.06.2017
comment
потому что вы вызываете это в классе Stack, так по какой причине мы не можем этого сделать?   -  person Phạm Lam    schedule 22.06.2017


Ответы (2)


Член private виден только другим членам того же класса, особенно в том же экземпляре.

ИЗМЕНИТЬ:

Голос «против» Частный модификатор обеспечивает соблюдение принципа инкапсуляции.

Вот цитата из похожего вопроса о C#, но принцип тот же.

Модификатор private обеспечивает соблюдение принципа инкапсуляции.

Идея состоит в том, что «внешний мир» не должен вносить изменения во внутренние процессы AClass, потому что реализация AClass может меняться со временем (и вам придется изменить весь внешний мир, чтобы исправить различия в реализации, что почти невозможно).

Когда экземпляр AClass получает доступ к внутренним компонентам другого экземпляра AClass, вы можете быть уверены, что оба экземпляра всегда знают детали реализации AClass. Если логика внутренних по отношению к AClass процессов изменена - все, что вам нужно сделать, это изменить код AClass.

Кроме того, это позволяет переопределить equals() или compareTo() без необходимости раскрывать атрибуты, участвующие в их оценке.

person C.Champagne    schedule 22.06.2017
comment
Почему это было разрешено? Я кажусь неинтуитивным. - person Abhishek Divekar; 22.06.2017
comment
@abhidivekar это не так, это совершенно нормально. - person jwenting; 22.06.2017
comment
@jwenting Возможно, у меня всегда было впечатление, что однажды созданный объект непроницаем для его частных членов. Я думал, что это должно сохраняться, даже когда внешние объекты того же класса передаются в качестве аргументов. В чем преимущество этой конструкции? - person Abhishek Divekar; 22.06.2017
comment
Выступление @abhidivekar — одна из причин, и очень важная. Доступ к полю напрямую, а не через метод доступа, быстрее. Хотя обычно это не очень важно, во время массовых операций это может иметь значение между приложением, которое работает хорошо, и приложением, которое останавливается. Другой причиной является доступ к вещам, у которых нет доступа, что, конечно, особенно важно для клонирования. - person jwenting; 22.06.2017
comment
Спасибо за разъяснение - person Abhishek Divekar; 22.06.2017

Это разрешено согласно спецификации языка. Частный доступ означает, что поле или метод видны экземплярам одного и того же CLASS, а не только экземпляру.

Это не специальное разрешение для определенных методов (таких как клонирование), а для любого метода в том же классе.

person jwenting    schedule 22.06.2017