覆盖(非)静态类中的私有方法

Posted

技术标签:

【中文标题】覆盖(非)静态类中的私有方法【英文标题】:Overriding private methods in (non-)static classes 【发布时间】:2014-12-18 20:43:00 【问题描述】:

我有这个测试代码示例:

公共类测试 私有静态类 Test3 私人无效打印1() System.out.println("1"); 私有静态类 Test4 扩展 Test3 私人无效打印1() System.out.println("2"); 公共静态无效主要(字符串[]参数) System.out.println("重写调用私有方法----"); OuterTest.Test1 test1 = new OuterTest.Test1(); OuterTest.Test2 test2 = new OuterTest.Test2(); OuterTest.Test1 test12 = new OuterTest.Test2(); test1.invokeOverriden(); test2.invokeOverriden(); test12.invokeOverriden(); System.out.println("从父类调用私有方法----"); test1.invokeNotOverriden(); test2.invokeNotOverriden(); test12.invokeNotOverriden(); System.out.println("一些魔法----"); Test3 test3 = new Test3(); Test4 test4 = new Test4(); Test3 test34 = new Test4(); test3.print1(); test4.print1(); test34.print1(); 类外测试 公共静态类 Test1 公共无效调用覆盖() 打印1(); 公共无效调用NotOverriden() 打印1(); 私人无效打印1() System.out.println("1"); 公共静态类 Test2 扩展 Test1 @覆盖 公共无效调用覆盖() 打印1(); 私人无效打印1() System.out.println("2");

首先,我认为一切正常:

重写对私有方法的调用---------------- 1 2 2

然后,如果我调用未实现的父方法,继承类的私有方法就会消失。可以解释为“所有私有方法都是最终的并且对派生类隐藏”,所以invokeNotOverriden() 对 Test2 类中的方法一无所知:

从父类调用私有方法---------------- 1 1 1

最后,在静态类中,当我调用非静态私有方法时,突然出现了一些魔法:

一些魔法---------------- 1 2 1

我期待1 2 2 在这里。为什么我错了?

【问题讨论】:

你不能重写私有方法——简单地说,就是这样。 我知道。而且我不会覆盖私有方法。我将类对象创建为Base b = new Inherited(),并调用了它的私有方法。我认为,b 现在是Inherited。为什么不是真的? 【参考方案1】:

您在some magic 部分中有1 2 1,因为私有方法在没有多态性的情况下被解析,编译器创建对包含在用Test3 声明的类型变量中的方法的调用。在Test3 中将print1 声明为非私有(因此,在Test4 中,因为禁止收紧方法的访问修饰符)并查看多态性的作用,因此您会得到预期的1 2 2


考虑更短的例子:

class Test 

    private static class Test3 
        private void print1() 
            System.out.println("non-polymorphic 1");
        

        void polymorphic() 
            System.out.println("polymorphic 1");
        
    

    private static class Test4 extends Test3 
        private void print1() 
            System.out.println("non-polymorphic 2");
        

        void polymorphic() 
            System.out.println("polymorphic 2");
        
    

    public static void main(String[] args) 
        Test4 t4 = new Test4();
        t4.print1();
        t4.polymorphic();

        System.out.println("======");

        Test3 t34 = new Test4();
        t34.print1();
        t34.polymorphic();
    


澄清 ...我对此答案的评论:多态性对访问数据字段无效,仅对方法有效。考虑:

private static class Test3 
    int i = 1;


private static class Test4 extends Test3 
    int i = 2;


public static void main(String[] args) 
    Test4 t4 = new Test4();
    System.out.println(t4.i);

    System.out.println("======");

    Test3 t34 = new Test4();
    System.out.println(t34.i);

尽管i 声明为非私有,t34.i 的值是1

【讨论】:

test34.getClass()Test$Test4 显示为其类,而不是 Test3 这是一个类的动态解析(多态),它仅用于访问non-private 成员(数据和方法)。对于private 数据/方法,访问是使用程序中使用的类型完成的。 所以static 不是魔法的根源,如果我理解正确的话。只有private 方法修饰符。谢谢。【参考方案2】:

私有方法只对声明它们的类可用,而不是该类的子类。

如果您想在子类中使用父类中的方法,则必须将其设为 protected

在您的最后一个案例中,您强制转换为 Test3,因此出于所有意图和目的,该类认为它是 Test3 并调用 Test3 的 print 方法。静态实例不强制转换(您总是用它们的限定名来调用它们),所以它们总是调用它们自己的私有方法。

【讨论】:

关于最后一种情况。但第一次,没有静态,test12 调用 Test2 私有方法,而不是 Test1【参考方案3】:

就像你说的,你不能覆盖private方法,改成protected

【讨论】:

以上是关于覆盖(非)静态类中的私有方法的主要内容,如果未能解决你的问题,请参考以下文章

Java继承方法隐藏(覆盖)

java中私有的属性、静态成员可以被子类继承吗?

子类能不能继承父类的成员变量

java中的内部类

Java中的覆盖和隐藏以及final关键字

java非静态内部类中的属性this$0