Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/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_Inheritance - Fatal编程技术网

对java中受保护的成员行为感到困惑

对java中受保护的成员行为感到困惑,java,inheritance,Java,Inheritance,我目前正在阅读SCJP学习指南。在第36页第1章中提到: 一旦包外部的子类继承了受保护的成员, 该成员(由子类继承)对于外部的任何代码都是私有的 子类,子类的子类除外。所以如果我们班的邻居 实例化子对象,即使类邻居与 类子对象,类邻居将无权访问子对象的继承(但受保护) 变量x。 但每当我试图通过以下代码检查时: //parent class in pkg#1: package com.main.parentPkg; public class ParentInSamePk

我目前正在阅读SCJP学习指南。在第36页第1章中提到:

一旦包外部的子类继承了受保护的成员, 该成员(由子类继承)对于外部的任何代码都是私有的 子类,子类的子类除外。所以如果我们班的邻居 实例化子对象,即使类邻居与 类子对象,类邻居将无权访问子对象的继承(但受保护) 变量x。

但每当我试图通过以下代码检查时:

    //parent class in pkg#1:
    package com.main.parentPkg;
    public class ParentInSamePkg {
     protected void methodInParent(){
       System.out.println("Inside ParentInSamePkg-->methodInParent");
     }
    }

    // First child class in pkg#2
    package com.main.childPkg;
    import com.main.parentPkg.ParentInSamePkg;
    public class ChildInOtherPkg extends ParentInSamePkg{
        void mthd(){
            System.out.println("inside ChildInOtherPkg:mthd");
            methodInParent();
        }
    }

    //Child class of child class inside pkg#3
    package com.main.grandChildPkg;
    import com.main.childPkg.ChildInOtherPkg;
    class GrandChild extends ChildInOtherPkg{
        void mthd(){
            System.out.println("inside GrandChild:mthd");
            methodInParent();
        }
        public static void main(String[] args) {
            GrandChild g=new GrandChild();
            g.mthd();
        }
    }
每当我执行上述代码并运行孙子类的main方法时,它将输出输出为:

inside GrandChild:mthd Inside ParentInSamePkg-->methodInParent 内孙:mthd 内部ParentInSamePkg-->methodInParent 因此,我感到困惑。根据这个概念,受保护的成员在继承子类后成为私有的,任何扩展这个子类的类都不能访问这个成员。但在上面的代码中,它是可访问的

请帮助我理解。

整个“受保护成员[…]成为私人”的概念听起来很奇怪

尽管Java语言规范通常很难理解,但它实际上说得很好:

对象的
受保护的
成员或构造函数可以从包的外部访问,在包中仅由负责该对象实现的代码声明

重要的部分是负责实施的部分。所有子类,子类,子类。。。负责对象的实现,这样他们就可以访问所有成员

这与它是自己的实例(
This
)还是另一个实例无关,只要它是包含代码的类的实例

或者,正如JLS所说:

设C为声明
受保护的
成员的类。仅允许在C的子类S的主体内访问

此外,如果Id表示实例字段或实例方法,则:

  • 如果访问是通过限定名
    Q.Id
    ,其中
    Q
    是表达式名,则当且仅当表达式
    Q
    的类型是
    S
    S
    的子类时,才允许访问

  • 如果访问是通过字段访问表达式
    E.Id
    ,其中
    E
    是主表达式,或者通过方法调用表达式
    E.Id(…)
    ,其中
    E
    是主表达式,当且仅当
    E
    的类型为
    S
    S
    的子类时,才允许访问


下表清楚地描述了所有类型的访问修饰符的行为


在受保护的情况下,只有存在于不同包中的非子类才能访问它。我们可以说,受保护的行为就像私有的一样如果且如果只有存在于不同包中的非子类才能访问它们。

您忽略了“子类的子类除外”这一条款的意义@Ted Hopp:那是什么?扩展子类的类仍然可以看到父类的
受保护的
成员。这是因为它们是“子类的子类”,而受保护的
成员就子类的子类而言,不会“成为子类的私有成员”;成员们仍然受到保护。@TedHopp:非常感谢:-)我非常理解这个概念。这意味着
protected
成员将保持可访问性并保持
protected
,直到继承树继续。如果我试图在非子类中访问子类的受保护成员,即不扩展子类并创建子类对象,则它会变成
私有的
。在我看来,研究指南中的措辞令人困惑,尽管它旨在澄清另一个潜在的困惑点:通常,
受保护的
成员可以访问同一包中的任何代码,即使是非子类。但是,子类包的非继承类无法访问子类包中来自不同包的父类的受保护成员(尽管子类的子类可以访问这些成员)。从这个意义上讲,他们的行为就好像是私人的。