Java中重写的方法可见性

Posted

技术标签:

【中文标题】Java中重写的方法可见性【英文标题】:Overrided method visibility in Java 【发布时间】:2013-09-30 16:06:31 【问题描述】:

假设我们有一个包“p1”:

package p1;

public class A 
    protected void method()  

...我们还有一个包“p2”:

package p2;

import p1.A;

public class B extends A  

class Tester 
    static void run() 
        new B().method(); //compile-time error
    

现在,如果我们尝试编译整个示例,我们将停留在标记行并显示编译时错误:编译器只是没有在 B 中看到目标方法。为什么会这样?

【问题讨论】:

因为method()protected? docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html 【参考方案1】:

受保护的方法在扩展基类(甚至在层次结构中)或同一个包内的所有类中都是可见的。您正在尝试在其他包和非扩展类中使用方法。

【讨论】:

但它是从 Tester 类调用的,它不扩展 A(或 B【参考方案2】:

由于Access Modifier 对A.method()protectedB extends A,所以存在protected B.method(),但需要注意的是,对于B 类中的protected method()method() 就像一个“类 B 的私有实体”,并且只能从任何对象引用“公共实体”,因此 new B().method() 会产生编译时错误。

要使您的代码正常工作,您可以更改访问修饰符。

package p2;

import p1.A;

public class B extends A 

    @Override
    public void method() 
        super.method();
    
 

【讨论】:

谢谢,我明白了。当然,我知道如果我将覆盖的方法标记为公共 - 每个人和任何地方都可以引用它。但仍然......我只是想做出一些逻辑,让我解释一下:1.受保护的方法对于子类和同一包内的类是可见的...... 2. B类“IS-A”类A(因为它扩展了一个) - 所以我假设“B”也有方法(因为“A”有它)并且它的可见性不能通过覆盖来缩小......所以 - 如果“B”有保护“方法” - 为什么不能从同一个包中访问? @IlyaGubarev 是有道理的,但问题是 method() 属于 A 类,它位于不同的包中,因此 Tester 无法访问。 @IlyaGubarev 尝试在B 中覆盖protected void method(),它只调用super.method(),这可能允许您从Tester 调用method() 好的,现在我想我已经明白了(“方法”是“A”的一部分,而不是“B”的一部分,即使“B”是-A“A”)。实际上,就像您之前评论的那样,我已经制作了一个覆盖的受保护版本。无论如何,这对我来说更多的是理论上的问题——这只是 javac 的一个令人惊讶的行为,尽管我真的很喜欢 Java 继承规则。感谢您提供有趣的观点。 哇。这是超级愚蠢的。我得出的结论是,包的可见性存在根本缺陷。 (我注意到了这一点,因为我删除了一个“多余的”覆盖并遇到了编译错误......)【参考方案3】:

超类的受保护方法在子类中变为私有。 如果您真的想从任何地方调用它,然后将其设为公共,或者,如果您仍想保护您的超类方法,请在调用(私有,继承)方法的子类中创建一个公共方法,子类中的内容如下:

public class B extends A  
      public void callTheMethod()
             method();
      

这可以很容易地被测试类调用

class Tester 
    static void run() 
        new B().callTheMethod(); //works well
    

【讨论】:

以上是关于Java中重写的方法可见性的主要内容,如果未能解决你的问题,请参考以下文章

Java 继承:降低构造函数与继承方法的可见性

为啥 Java 允许增加子类中受保护方法的可见性?

Java中枚举值的可见性

java 可见性简单总结

Java中同步的可见性效果

对比Java学Kotlin可见性修饰符