Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,为什么可以';超级类方法是否从子类实例访问受保护的或私有的方法/变量?_Java_Oop_Class_Inheritance_Instance - Fatal编程技术网

在Java中,为什么可以';超级类方法是否从子类实例访问受保护的或私有的方法/变量?

在Java中,为什么可以';超级类方法是否从子类实例访问受保护的或私有的方法/变量?,java,oop,class,inheritance,instance,Java,Oop,Class,Inheritance,Instance,让我们从另一个行为开始:即使将方法/变量声明为private,同一类的另一个实例也可以访问它。没关系,我可以接受。我称这些类为private,而不是实例private 现在是问题部分: 例如,在运行时,我希望能够检查这个类中的所有字符串变量都不为null,如果为null,则应将它们更改为字符串“null” 我可以使用反射遍历变量并得到它们的值。但是如果我扩展我的类并添加私有的甚至是受保护的变量,我的基类就不能访问它们。在使用变量之前,我必须setAccessible 所以请向我解释为什么基类(超

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

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

我可以使用反射遍历变量并得到它们的值。但是如果我扩展我的类并添加私有的甚至是受保护的变量,我的基类就不能访问它们。在使用变量之前,我必须
setAccessible

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

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

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


更新:
根据答案,我还想知道:为什么从同一个类访问另一个实例的私有变量不被视为违反封装?

这很简单,因为它违反了封装。另一个类不应该深入到您的类中,并且在处理一些事情,即使您对该类进行了泛化。例如,车辆是如何了解车辆的?基类的全部要点是提供子类,但就像过度保护的父类一样,您的建议太多了。

这都是关于继承和封装的

Java的可见性规则声明

  • 只能在定义私有成员的类中访问它们
  • 受保护的成员只能在中访问
    • 定义它们的类
    • 定义它们的类的子类
    • 与定义它们的类位于同一包中的其他类

  • 当然,正如您所提到的,在反思中,您可以更改规则(除非安全管理者禁止)

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

    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; }
    }
    
    您建议使用什么语法来访问
    Test2
    中的私有成员
    a
    。编写
    Test1
    时,
    Test2
    甚至可能不存在

    同样,基类(超类)不知道它是何时从继承来的。要让基类知道它何时被继承,您必须能够在从基类继承时修改基类。您是否建议我在编写以下内容时以某种方式修改我的
    ArrayList
    本地副本:

    class MyArrayList extends ArrayList
    
    当我决定在你的计算机上运行我的代码的那一天,你会得到我的
    ArrayList
    的修改副本,它知道
    MyArrayList
    ,还是我会在你的计算机上修改副本


    这些问题能以某种方式克服吗?当然允许它有什么价值吗?我看不到任何内容。

    要回答您的更新问题(因为原始问题已经得到了很好的回答),private的目的是隐藏实现细节,以便这些实现细节不会成为依赖项。这就是面向对象编程的本质——封装,通过将不同的部分隔离到各自的区域来确保复杂性的可管理性

    因为类知道它自己的实现——它定义了它,所以限制对其他实例的访问并没有什么好处,因为类实现声明了它已经暴露于所有这些细节的所有私有实例


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

    @Tetsujin:您刚才让我笑了;)那么为什么从同一个类实例访问另一个实例的私有变量不被认为违反了封装?@Tetsujin同意,我在问为什么设计是这样的?为什么使用新的修饰符是不好的:unprotected,在这种情况下它不是公共的;这是类级封装。这就是大多数OO语言的实现方式。这不是一个真正的问题,因为一个类控制着它所有实例中的数据。那么为什么从同一个类实例访问另一个实例的私有变量不被认为违反了封装呢?汽车应该能够限制BMW只有轮子而没有翅膀,因为如果BMW有翅膀,它就不是汽车(即使它“内部”使用翅膀),因为我是这一类人。你不能做你在课堂外谈论的事情,因此封装是得体的。在类中,您可以修改该类的另一个实例的私有成员。这怎么会违反任何规定?我在班上!我可以更改与我想要的类关联的任何内容,为什么不允许呢?在您的示例中,Test2实例实际上有两个变量:Test1.a和Test2.a,每个变量只能从它的类访问。Test1可以在Test2实例中更改Test1.a的值,这被语言认为是正常的,但对Test2没有影响,即使Test1“认为”它有影响。当子类用作基类时会破坏兼容性的例子有很多。这和我问的有什么不同?我不知道你想说什么。我回到我最初的问题:1)Test2可以使用什么样的语法来访问或更新其父类的私有成员?2) Test1如何知道如何将其内部成员公开给一个可能尚未编写的类?3) 你是如何传播t的