有效的Java:clone()私有访问

时间:2017-06-22 11:26:48

标签: java clone private-members effective-java

在Bloch的Effective 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的{​​{1}}类型的新对象。我们随后克隆result,尽管result.elements类将Stack定义为私有成员。发生了什么,为什么允许?

2 个答案:

答案 0 :(得分:3)

private成员只能从同一个班级的其他成员看到,尤其是在同一个实例中。

编辑:

投票结束 private修饰符强制执行Encapsulation原则。

以下是similar question about C#的引用,但原则是相同的。

  

private修饰符强制执行封装原则。

     

这个想法是“外部世界”。不应该对AClass进行更改   内部流程,因为AClass实现可能会随着时间而改变   (你必须改变整个外部世界来修复它   实施方面的差异 - 这几乎是不可能的。)

     

当AClass的实例访问其他AClass实例的内部时 -   你可以确定这两个实例总是知道细节   AClass的实现。如果是AClass内部逻辑流程   已更改 - 您所要做的就是更改AClass的代码。

此外,允许覆盖equals()compareTo(),而不必公开其评估中涉及的属性。

答案 1 :(得分:0)

根据语言规范允许这样做。私有访问意味着对同一CLASS的实例可以看到字段或方法,而不仅仅是实例。

这对某些方法(如克隆)没有特殊权限,但对于同一类中的任何方法都没有。