在Java中,为什么超类方法不能从子类实例访问受保护的或私有的方法/变量?

让我们从另一个行为开始:即使您将方法/变量声明为私有,同一个类的另一个实例也可以访问它 . 没关系,我可以忍受它 . 我将这些类称为私有而不是实例私有 .

现在问题部分:例如,在运行时我希望能够检查 this 类中的所有String变量都不为null,如果它们为null,则应将它们更改为字符串"NULL" .

我可以使用反射来运行变量并获取它们的值 . 但是如果我扩展我的类并添加私有甚至保护变量,我的基类就无法访问它们 . 在使用它们之前,我必须对变量进行 setAccessible .

所以请向我解释为什么基类(超类)不能从其子类访问私有/受保护变量 . 它是它的子类,所以我不明白 . 这背后有什么想法?

我知道超类不应该知道它的子类,但在我的例子中它是有意义的,不是吗?

是因为我不能或不应该以这种方式限制我的子类?


Update: 根据答案,我也想知道:为什么来自同一类的私有变量被视为违反封装?

回答(4)

3 years ago

这很简单,因为它违反了封装 . 另一堂课不应该进入你的 class ,并且不能搞乱你的东西,即使你把这个课程概括了 . 例如,车辆如何了解汽车的任何信息?基类的重点是提供子类,但是像过度保护的父类一样,你所建议的内容太多了 .

3 years ago

要回答您的更新问题(因为原始问题已得到很好的回答),私有的目的是隐藏实现细节,以便这些实现细节不会成为依赖关系 . 这是面向对象编程的本质 - 封装确保通过将不同部分隔离到自己的区域来保持复杂性 .

由于类知道它自己的实现 - 它定义了它,因此限制对其他实例的访问没有任何好处,因为类实现声明它已经暴露给所有这些细节的所有私有实例 .

在这种情况下隐藏它实际上会增加复杂性,因为您必须添加额外的访问级别以允许类级别可见性而不是实例级别可见性,而不实际封装任何进一步的复杂性 .

3 years ago

这都是关于继承和封装的 .

Java的可见性规则说明了这一点

  • 私有成员只能在定义它们的类中访问

  • 受保护的成员只能访问

  • 定义它们的类

  • 定义它们的类的子类

  • 与定义它们的类在同一个包中的其他类

当然,正如您所提到的,在反射中您可以更改规则(除非SecurityManager禁止它)

3 years ago

我倾向于从务实和现实的角度来看待它:

public class Test1 {
    private int a = 1;

    public static void main(String s[]) {
        System.out.println((new Test1()).a);
        System.out.println((new Test1()).getA());
        System.out.println((new Test2()).getA());
    }

    public int getA() { return a; }
}

class Test2 extends Test {
    private int a = 2;

    public int getA() { return a; }
}

您建议使用什么语法 Test1 来访问 Test2 中的私有成员 a . 写入 Test1 时, Test2 可能甚至不存在 .

同样,基类(超类)不知道它何时被继承 . 要允许基类知道何时继承它,您必须能够在继承基类时修改它 . 当你写信时,你是否建议我以某种方式修改 ArrayList 的本地副本:

class MyArrayList extends ArrayList

当我决定在您的计算机上运行我的代码时会发生什么,您是否获得了 ArrayList 的修改后的副本,了解 MyArrayList ,或者我是否以某种方式修改了您计算机上的副本?

能以某种方式克服这些问题吗?当然 . 允许它有什么 Value 吗?没有我能看到的 .