【问题标题】:Why is there a compilation error when accessing protected method from subclass in Java?为什么从 Java 中的子类访问受保护的方法时会出现编译错误?
【发布时间】:2014-04-20 02:54:42
【问题描述】:

我正在阅读 Java 中的 protected 修饰符,哪些字段可以在同一个包和子类中访问。

现在我已经写了一些代码。

package com;

public class Parent {

    protected void print()
    {
        System.out.println("dFDF");
    }
}

现在是子类。

package abstraact.concept;

import com.Parent;

    public class BaseParent extends Parent{

        public void printNum()
        {
            Parent p = new Parent();
            p.print(); /** Getting error here */
                    // The method print() from the type Parent is not visible
        }



        public static void main(String[] args) {
            BaseParent pp = new BaseParent();
            pp.printNum();

        }
    }

为什么我会出错? 由于受保护的方法/变量可以从子类访问。

【问题讨论】:

标签: java inheritance subclass protected


【解决方案1】:

这是Java中常见的“悖论”,其实一点也不悖论。简而言之,由于语言的安全性(可见性)规则,无法通过另一个包中的对象引用访问受保护的方法。

一旦声明了一个新对象,它所拥有(或允许)的可见性由代码所属的包控制,而不是由继承层次结构控制。

打电话

super.print();

this.print();

会起作用的。

【讨论】:

  • 您能否详细说明或给我链接,我可以阅读它?
  • 基本思想是父对象引用与您声明它的任何其他对象引用具有相同的访问限制。要利用层次结构,您必须专门使用 this 或 super。
  • @Thinker:做一些关于继承和组合的谷歌搜索,了解两者之间的区别。还要理解一个对象像所有其他对象一样被对待,并且层次结构以一种特殊的方式被对待。
【解决方案2】:

请仔细尝试并理解该声明。受保护的仅在派生类中可见。这对于继承来说是正确的。但是,当您创建 Parent 类型的 Object 时,您并没有使用继承。这意味着 Parent 不是在那里派生的,并且 parent 的功能受到保护。但是,如果您使用super.print(),它将通过继承引用 Parent 并获得该功能。

所以你的解决方案是替换:

Parent p = new Parent();
p.print();

super.print();

【讨论】:

    【解决方案3】:

    调用super.print() 而不是声明一个新的Parent 对象

    【讨论】:

      【解决方案4】:

      如果包不同,则无法访问受保护的方法。您可以按如下方式访问此方法:

       BaseParent pp = new BaseParent();
       pp.print();
      

      super.print();
      

      【讨论】:

        【解决方案5】:

        将 print 方法声明为 protected 允许它被子类 BaseParent 继承。

        当 BaseParent 中的代码引用其自己的(继承的)“print”版本时,这是允许的,因为它已成为该子类的一部分。 但是,子类仍然不能引用父类自己的方法版本(尽管在同一个包中会推翻这一点),因为“protected”关键字只允许其他包中的子类继承和使用他们自己的方法版本。

        在挣扎了一段时间后,我才明白为什么会出现错误,这就是我的想法。

        Oracle 在第 6.6.2 节 http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.2.1 中的文档以自己的方式说明了这一点:

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

        因此 BaseParent 只负责自己继承的打印方法,而不是父类中的原始方法。

        【讨论】:

          猜你喜欢
          • 2015-08-14
          • 2011-04-17
          • 2014-04-17
          • 2012-11-25
          • 1970-01-01
          • 2013-04-06
          • 1970-01-01
          • 2013-11-25
          • 2012-06-25
          相关资源
          最近更新 更多