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

时间:2014-10-23 08:06:48

标签: java inheritance static override static-methods

我有这个测试代码示例:

public class Test {

    private static class Test3 {

        private void print1() {
            System.out.println("1");
        }
    }
    private static class Test4 extends Test3 {

        private void print1() {
            System.out.println("2");
        }
    }

    public static void main(String[] args) {
        System.out.println("Overriden call to private method ----------------");
        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("Call to private method from parent class ----------------");

        test1.invokeNotOverriden();
        test2.invokeNotOverriden();
        test12.invokeNotOverriden();

        System.out.println(" Some magic ----------------");

        Test3 test3 = new Test3();
        Test4 test4 = new Test4();
        Test3 test34 = new Test4();

        test3.print1();
        test4.print1();
        test34.print1();
    }
}

class OuterTest {

    public static class Test1 {
        public void invokeOverriden() {
            print1();
        }
        public void invokeNotOverriden() {
            print1();
        }

        private void print1() {
            System.out.println("1");
        }
    }

    public static class Test2 extends Test1 {

        @Override
        public void invokeOverriden() {
            print1();
        }
        private void print1() {
            System.out.println("2");
        }
    }
}

首先,我认为它应该起作用:

Overriden call to private method ----------------
1
2
2

然后,如果我调用了非实现的父方法,则继承类的私有方法消失。它可以解释为"所有私有方法都是最终的并且隐藏在派生类中#34;所以invokeNotOverriden()对Test2类中的方法一无所知:

Call to private method from parent class ----------------
1
1
1

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

Some magic ----------------
1
2
1

我在这里预计1 2 2。为什么我错了?

3 个答案:

答案 0 :(得分:2)

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


考虑更短的例子:

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 :(得分:1)

私有方法仅适用于声明它们的类,而不是该类的子类。

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

在你的最后一种情况下,你已经转换为Test3,所以对于所有意图和目的,该类认为它是Test3并调用Test3的print方法。静态实例不会被强制转换(您总是使用其限定名称调用它们),因此它们总是调用自己的私有方法。

答案 2 :(得分:0)

就像你说的那样,你无法覆盖private方法,将其设为protected