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

时间:2015-12-04 05:50:12

标签: java inheritance

我目前正在阅读SCJP学习指南。在第1章第36页中,它被提及为:

  

一旦子类外包继承受保护的成员,   该成员(由子类继承)变得对外部任何代码都是私有的   子类,子类的子类除外。所以如果是邻居类   实例化一个Child对象,即使类Neighbor与同一个包在同一个包中   class Child,class Neighbor无法访问Child的继承(但受保护)   变量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();
        }
    }

每当我执行上面的代码并运行GrandChild类的main方法时,它会将输出打印为:

inside GrandChild:mthd
Inside ParentInSamePkg-->methodInParent

因此,我很困惑。根据概念,受保护的成员在子类中继承后变为私有,并且任何扩展此子类的类都无法访问此成员。但在上面的代码中,它是可访问的。

请帮助我理解。

2 个答案:

答案 0 :(得分:1)

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

如果受到保护,它只能由不同包中存在的非子类访问。我们可以说受保护的行为就像私有,如果只有它们被非子类访问不同的包装。

答案 1 :(得分:0)

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

虽然Java语言规范通常非常难以阅读,但它实际上说的很好:

  

<强> 6.6.2. Details on protected Access

     

对象的getInputArguments() 成员或构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。

重要的部分是负责实施部分。所有子类,子子类,子子类......都负责实现对象,因此他们都可以访问该成员。

这不管是它自己的实例(protected)还是其他实例,只要它是包含代码的类的实例。

或者,正如JLS接着说:

  

<强> 6.6.2.1. Access to a protected Member

     

设C为声明this成员的类。只允许在C的子类S的主体内访问。

     

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

     
      
  • 如果访问权限是限定名protected,其中Q.Id ExpressionName ,那么当且仅当类型为表达式QQS的子类。

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

  •