inheritance中的私有方法

这是一个有趣的代码片段:

public class Superclass { public static void main (String[] args){ Superclass obj = new Subclass(); obj.doSomething(); #prints "from Superclass" } private void doSomething(){System.out.println("from Superclass");} } class Subclass extends Superclass { private void doSomething(){System.out.println("from Subclass");} } 

我知道子类不会inheritance其父级的私有成员,但是obj设法调用它应该没有访问权限的方法。 在编译时,obj的类型为Superclass,在运行时类型为Subclass。

这可能与doSomething()的调用发生在驱动程序类中的事实有关,该驱动程序类恰好是它自己的类(以及为什么可以首先调用doSomething())。

所以问题归结为,obj如何访问其父级的私有成员?

你自己回答了。 由于私有方法不是inheritance的,因此超类引用会调用自己的私有方法。

私有方法仅适用于所有者。

甚至不是所有者的孩子,亲戚或朋友。

 Superclass obj = new Subclass(); 

在这一点上, obj既是东西,也是SubclassSuperclass对象。 在变量声明中使用Superclass这一事实只是一个问题。

当你这样做: obj.doSomething() ,你告诉编译器调用obj的私有方法doSomething() 。 因为您是从Superclass的主静态方法执行的,所以编译器可以调用它。

如果您将使用Subclass的main方法而不是Superclass ,那么您将无法访问该方法,因为正如您所说,它既不是inheritance的,也不是Subclass定义的一部分。

所以基本上你正确理解了inheritance。 问题与私有方法的可见性有关。

它的工作原理是因为你从Superclass的方法中转换为Superclass 。 在该上下文中,编译器可以使用Superclass.doSomething

如果要将超类和子类更改为两个不同的任意类A和B,与包含main方法的类无关,并尝试使用相同的代码,编译器会抱怨无法访问该方法。

当你使用这一行时:

 Superclass obj = new Subclass(); 

您将Subclass转换为超类对象,该对象仅使用超类的方法和相同的数据。 如果将它转换回子类,则可以再次使用Subclass方法,如下所示:

 ((Subclass)obj).doSomething(); #prints "from Subclass" 

由于对象obj的引用类型是SuperClass ,因此对doSomething()的调用尝试访问SuperClass本身定义的私有方法(不能覆盖私有方法)。 由于doSomething()可以在SuperClass访问,因此main方法可以调用doSomething()而不会给出任何错误。

希望这可以帮助! 🙂

为什么首先可以调用doSomething()?

为什么不? objSubclassSuperclass一个实例,并且doSomething()Superclass声明并且在其中使用obj ,因此您可以访问Superclass.doSomething() ,您可以尝试重命名您的方法( 例如doAnotherThing() )你仍然可以访问它。

obj如何访问其父级的私有成员?

私有方法没有父/子,并且obj也是一类Superclass ,因此它可以访问在其中声明的所有私有方法/字段,因为在此类中使用了obj 。 如果您不在Superclass或具有Superclass作为成员的类(嵌套类)之外,您将失去此访问权限。

所以呢?

SuperClass的私有方法和SubClass的私有方法之间没有任何关系/inheritance,即使它们具有相同的名称和签名,来自Java语言规范,Java SE 8版 :

私有方法和在最终类(第8.1.1.2节)中立即声明的所有方法的行为就像它们是最终的一样,因为不可能覆盖它们。

要理解这个问题,您可以将私有方法与超类和子类的成员变量相关联。

所以我们知道成员变量不会在子类中被覆盖。

例如:

 Class A{ int i = 10; } Class B extends A{ int i = 11; } Class C extends A { int i = 12; } A a1 = new B(); print(a1.i) // Will print 10 A a2 = new B(); print(a2.i) // Will print 10 

类似的方式,当没有inheritance引用变量时,将考虑超类。

当我们在派生类中定义具有相同名称的私有方法时,它将成为一个新方法,因为派生类不会inheritance私有成员。

由于私有方法在类外部甚至不可见,我们永远不能从派生类调用基类私有方法,它会抛出一个编译错误:

线程“main”中的exceptionjava.lang.Error:未解决的编译问题:Base类型的方法aPrivateMethod()不可见

我们可以使用向下转换到父类引用来调用派生类私有方法,该方法只能在该派生类中访问。