子类中的私有字段在超类中是可访问的

Private field in subclass is accessible in superclass

用JLS写的(见8.3节):

“子class可能可以访问超级class的私有字段——例如,如果 两个 class 都是同一个 class 的成员。然而,私人领域永远不会 由子class继承。

你能举个例子吗?

我知道我们可以这样写:

public class MyClass {
    private int x = 1;

    public void testExample(MyClass m) {
        m.x = 2;
    }
}

这里我们访问私有字段 m.x 但我们没有 "Super Class" - "Sub Class" 这里。

这是在谈论嵌套 classes - 这是一个例子:

public class Test {
    public static void main(String[] args) {
        new Subclass(10).foo();
    }

    static class Superclass {
        private int x;

        Superclass(int x) {
            this.x = x;
        }
    }

    static class Subclass extends Superclass {
        Subclass(int x) {
            super(x);
        }

        public void foo() {
            Superclass y = this;
            System.out.println(y.x);
        }
    }
}

有效是因为JLS 6.6:

Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor

这里 x 的使用是在 Test 的主体内,它是顶层 class,包含 x 的声明...尽管如果您尝试使用 x 不合格的,或者只是 this.x,但失败了......正是因为 x 实际上不是 inherited(根据文章您引用的规格)。

方法"visibility"——顾名思义——是关于方法和变量在什么地方"visible"给程序员的。作为一般契约,class 范围内的变量在 class 定义中始终可见,即使它们被声明为私有并被实例化对象(不是 "this")引用class.

在设计方面,有关可见性和封装的规则旨在帮助确保程序员不会意外访问变量和方法,这些变量和方法在意外使用时会破坏功能。例如,如果您要手动调用

,您将中断 java.util.Random 工作方式的联系
private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}

(来源于SunJDK源码)

但是,在您编写的代码范围内,通常认为可以在定义为 class 类型的对象上调用 private variables/methods,因为假定程序员和问题代码的编写者,您拥有正确管理代码所需的权限、代理和专业知识。

所以一般来说,不管变量是否声明为private,如下代码:

public class Test {
    private float internalValue;
    public boolean isBigger(Test t) {
        return internalValue > t.internalValue;
    }
}

永远有效。