无法从父级减少方法inheritance方法的可见性

我收到了这个编译错误:

您无法降低inheritance方法的可见性。

我有以下代码

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方法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)将不得不抛出某种运行时exception – 不允许这样做可以确保aMethod(p)