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