11

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

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");}

}

我知道子类不会继承其父类的私有成员,但在这里 obj 设法调用它不应访问的方法。在编译时 obj 是 Superclass 类型,在运行时是 Subclass 类型。

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

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

4

9 回答 9

18

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

甚至对主人的孩子、亲戚或朋友也不行。

于 2013-01-18T03:55:08.247 回答
15

你自己回答了。由于私有方法不被继承,超类引用调用它自己的私有方法。

于 2013-01-18T03:47:04.960 回答
5

它之所以有效,是因为您正在SuperclassSuperclass. 在这种情况下,Superclass.doSomething编译器可以使用。

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

于 2013-01-18T04:01:23.447 回答
5
Superclass obj = new Subclass();

在这一点上,obj既是事物,Subclass又是Superclass对象。您在变量声明中使用的事实Superclass只是转换它的问题。

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

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

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

于 2013-03-17T20:04:17.193 回答
3

当您使用此行时:

Superclass obj = new Subclass();

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

((Subclass)obj).doSomething(); #prints "from Subclass"
于 2013-01-18T03:50:31.047 回答
3

由于对象的引用类型objSuperClass,调用 会doSomething()尝试访问其SuperClass自身定义的私有方法(私有方法不能被覆盖)。正如doSomething()在 中可访问的那样SuperClass,该main方法可以在doSomething()不给出任何错误的情况下调用。

希望这可以帮助!:-)

于 2014-10-10T14:56:20.670 回答
1

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

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

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

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

所以呢?

SuperClass的私有方法和私有方法之间没有关系/继承SubClass,即使它们具有相同的名称和签名,来自Java Language Specification, Java SE 8 Edition

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

于 2017-12-31T21:34:09.903 回答
0

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

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

例如:

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 

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

于 2016-10-12T15:14:26.810 回答
-1

当我们在派生类中定义一个同名的私有方法时,它就成为一个新方法,因为派生类不继承私有成员。

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

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

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

于 2015-12-31T22:41:30.233 回答