为什么内部类可以覆盖私有final方法?

时间:2012-03-01 21:02:01

标签: java override inner-classes final

我想知道将私有方法声明为最终是否有意义,我认为这没有意义。但我想象有一种独特的情况并编写了代码来解决它:

public class Boom {

    private void touchMe() {
        System.out.println("super::I am not overridable!");
    }

    private class Inner extends Boom {

        private void touchMe() {
            super.touchMe();
            System.out.println("sub::You suck! I overrided you!");
        }
    }

    public static void main(String... args) {
        Boom boom = new Boom();
        Boom.Inner inner = boom.new Inner();
        inner.touchMe();
    }
}

它编译和工作。 “我应该让touchMe()最终成功”我想到并做到了:

public class Boom {

    private final void touchMe() {
        System.out.println("super::I am not overridable!");
    }

    private class Inner extends Boom {

        private void touchMe() {
            super.touchMe();
            System.out.println("sub::You suck! I overrided you!");
        }
    }

    public static void main(String... args) {
        Boom boom = new Boom();
        Boom.Inner inner = boom.new Inner();
        inner.touchMe();
    }
}

它也有效并告诉我

chicout@chicout-linlap:~$ java Boom
super::I am not overridable!
sub::You suck! I overrided you!

为什么?

5 个答案:

答案 0 :(得分:87)

私有方法不能被覆盖(私有方法不会被继承!)事实上,如果你声明私有方法是最终的,那也没什么区别。

您声明的两种方法Boom.touchMeBoom.Inner.touchMe是两个完全独立的方法,它们碰巧共享相同的标识符。 super.touchMe引用与touchMe不同的方法的事实仅仅是因为Boom.Inner.touchMe 阴影 Boom.touchMe(而不是因为它覆盖了它)。

这可以通过多种方式得到证明:

  • 正如您自己发现的那样,如果您将方法更改为公开,编译器会抱怨,因为 突然尝试覆盖最终方法。

  • 如果您将方法保密并添加@Override注释,编译器会抱怨。

  • 正如alpian指出的那样,如果你将Boom.Inner对象强制转换为Boom对象(((Boom) inner).touchMe()),则会调用Boom.touchMe(如果它确实被覆盖了) ,演员无关紧要。)

相关问题:

答案 1 :(得分:8)

我认为这里有两种不同的方法可以通过改变你的主要方式很好地证明:

public static void main(String... args) {
    Boom boom = new Boom();
    Boom.Inner inner = boom.new Inner();
    inner.touchMe();
    System.out.println("And now cast it...");
    ((Boom)(inner)).touchMe();
}

现在打印:

super::I am not overridable!
sub::You suck! I overrided you!
And now cast it...
super::I am not overridable!

super调用Inner的原因是因为您在超类(touchMe)中查找了一个名为Boom的方法,确实存在并且Inner可见,因为它属于同一类。

答案 2 :(得分:6)

私有方法对于子类或任何其他类是不可见的,因此它们可以具有相同的名称,但不会相互重叠。

尝试添加@Override注释 - 您将收到编译器错误。

答案 3 :(得分:2)

您可以覆盖该方法,因为每个类都是private

答案 4 :(得分:1)

您刚刚声明了另一个具有相同名称的方法。您可以调用类的私有成员,因为内部类本身就是类的成员。希望这个修改能够详细解释它。

public class Boom {

    private final void touchMe() {
        System.out.println("super [touchMe] ::I am not overridable!");
    }

    public void overrideMe(){
        System.out.println("super [overrideMe]::I am overridable!");
    }

    private class Inner extends Boom {

        private void touchMe() {
            super.touchMe();
            System.out.println("sub [touchMe]::You suck! I overrided you!");
        }

        public void overrideMe(){
            System.out.println("sub [overrideMe] ::I overrided you!");
        }
    }

    public static void main(String... args) {
        Boom boom = new Boom();
        Boom.Inner inner = boom.new Inner();

        inner.touchMe();

        Boom newBoom = inner;
        newBoom.touchMe();
        newBoom.overrideMe();
    }
}



super [touchMe] ::I am not overridable!
sub [touchMe]::You suck! I overrided you!
super [touchMe] ::I am not overridable!
sub [overrideMe] ::I overrided you!