具有受保护类的继承

时间:2012-08-10 20:05:41

标签: java inheritance

这是继承的代码示例,而代码运行正常。我无法理解此代码的输出,请向我解释。

class R {
    private void S1() {
        System.out.println("R:S1");
    }

    protected void S2() {
        System.out.println("R:S2");
    }

    protected void S1S2() {
        S1();
        S2();
    }
}

class S extends R {
    private void S1() {
        System.out.println("S:S1");
    }

    protected void S2() {
        System.out.println("S:S2");
    }
}

public class Inheritance {
    public static void main(String srgs[]) {
        new S().S1S2();
    }
}

输出结果为:

R:S1
S:S2

为什么第一次调用,R类'S1而S类'S2'。

2 个答案:

答案 0 :(得分:3)

R.S1 私有,因此不会多态调用,S.S1不会覆盖它。

R.S2 受保护,因此S.S2会覆盖它,当您在S2的实例上调用S2时(即使它只是R 静态已知为S.S2)的实例,m2将被调用。

来自section 8.4.8.1 of the JLS

  

在类C中声明的实例方法m1将覆盖在类A中声明的另一个实例方法m2,如果以下所有条件都为真:

     
      
  • C是A的子类。

  •   
  • m1的签名是m2签名的子签名(§8.4.2)。

  •   
  • 或者:

         
        
    • m2在与C相同的包中公开,受保护或声明为默认访问权限,或

    •   
    • m1会覆盖方法m3(m3与m1不同,m3与m2不同),这样m3会覆盖m2。

    •   
  •   

请注意{{1}}不能保密。

答案 1 :(得分:0)

在R中,S1是私有的,因此无法覆盖。因此,在R#S1S2中对S1的调用总是调用R#S1。 S中的S1完全不相关。 [附注:你需要更好的名字。]

但S2不是私有的,所以它可以被覆盖 - 而且它是。

Java VM可以通过了解无法覆盖私有函数来获得良好的性能提升。没有什么,甚至不是后代的课程,都应该受到课堂私人细节的影响。