我得到了这个编译器错误:
不能降低继承方法的可见性。
我有以下代码
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");
}
}
这里父类有一个func()
方法,它是公共的,并被私有的子类TestClass
覆盖。现在编译器抛出我不能降低可见性的错误。从技术上讲,每当我创建一个TestClass
的对象分配给类型父对象时,由于func()
方法被重写,TestClass的func()总是会被调用,那么我们为什么要注意可见性呢?这个错误背后的原因是什么?有人能给我解释清楚吗?
这是因为子类对于void func()
方法具有private
的可见性,但超类具有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
要"修复"此问题,请使子类的func
方法public
:
public class TestClass extends parent {
...
public void func() { // give it public visibility
System.out.println("in child");
}
}
请使用标准命名约定;在这种情况下,"类应该以大写字母"开头,即Parent
而不是parent
来自Java语言规范第8.4.8.3节:
重写或隐藏方法的访问修饰符(§6.6)必须提供至少与重写或隐藏的方法一样多的访问权限,否则将发生编译时错误。更详细地说:
- 如果重写或隐藏的方法是公共的,那么重写或隐藏方法必须是公共的;否则,将发生编译时错误
- 如果覆盖或隐藏的方法是受保护的,那么覆盖或隐藏方法必须是受保护或公共的;否则,将发生编译时错误
- 如果重写或隐藏的方法具有默认(包)访问权限,则重写或隐藏方法不得为私有方法;否则,将发生编译时错误
请注意,在这些术语的技术意义上,私有方法不能被隐藏或重写。这意味着子类可以声明一个与其超类中的私有方法具有相同签名的方法,并且不要求该方法的返回类型或throws子句与该超类中私有方法的那些具有任何关系。
毕竟,您只希望private
方法由同一类中的代码调用——如果它最终因重写公共方法而被调用,那将非常令人困惑。
如果你仔细想想,不能做到这一点是有意义的。。
原因是,您可以将子对象当作父对象来传递(即,您可以使用父类型作为TestClass实例的引用类型)。
例如
parent p = new TestClass();
其他地方可能有一些代码使用parent
类型并调用该方法:
例如
public static void aMethod(parent aParent){
p.func();
}
如果能够降低方法的可见性,那么调用aMethod(p)
将不得不抛出某种运行时异常——不允许这样做可以确保不需要这样做。