无法降低从父方法继承的方法的可见性

2022-09-05 00:00:25

我得到这个编译器错误:

不能降低继承方法的可见性。

我有以下代码

class Parent {      
    public void func() {
        System.out.println("in Parent");
    }
}

public class TestClass extends Parent {    
    public static void main(String args[]) {
        parent obj=new TestClass();
        obj.addTest();
    } 

    private void func() {
        System.out.println("in child");         
    }
}

这里的父类具有公共方法,并被私有子类覆盖。现在编译器抛出我无法降低可见性的错误。从技术上讲,每当我创建一个分配给类型父对象的对象时,既然方法被覆盖了,TestClass的func()将始终被调用,那么为什么我们应该注意可见性呢?这个错误背后的原因是什么?有人可以清楚地解释我吗?func()TestClassTestClassfunc()


答案 1

这是因为子类具有 方法的可见性,但超类具有 可见性 。privatevoid func()public

如果你的代码被允许编译,如果你这样做,它会在运行时爆炸:

parent p = new TestClass();
p.func(); // boom - func is public in parent, but TestClass's impl is private, so no access would be allowed

要“修复”此问题,请使子类的方法:funcpublic

public class TestClass extends parent {
    ...
    public void func() { // give it public visibility
        System.out.println("in child");         
    }
}


请使用标准命名约定;在这种情况下,“类应以大写字母开头” - 即不Parentparent


答案 2

来自 Java 语言规范的 8.4.8.3 节

重写或隐藏方法的访问修饰符 (§6.6) 必须提供至少与重写或隐藏方法一样多的访问权限,否则会发生编译时错误。更详细地说:

  • 如果被覆盖或隐藏的方法是公共的,则重写或隐藏的方法必须是公共的;否则,将发生编译时错误。
  • 如果被覆盖或隐藏的方法受到保护,则覆盖或隐藏方法必须受到保护或公开;否则,将发生编译时错误。
  • 如果重写或隐藏的方法具有默认(包)访问权限,则重写或隐藏方法不得为私有方法;否则,将发生编译时错误。

请注意,私有方法不能在这些术语的技术意义上被隐藏或覆盖。这意味着子类可以声明与其超类中的私有方法具有相同签名的方法,并且不要求此类方法的返回类型或抛出子句与超类中私有方法的返回类型或抛出子句具有任何关系。

毕竟,您只期望由同一类中的代码调用一个方法 - 如果由于重写公共方法而最终调用它,那将非常令人困惑。private


推荐