Почему внутренний класс может переопределить private 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() final", - подумал я и сделал это:

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 66

5 ответов:

частные методы не могут быть переопределены (Private методы не наследуются!) На самом деле, это не имеет никакого значения, если вы объявляете частный метод final или нет.

два метода, которые вы объявили, Boom.touchMe и Boom.Inner.touchMe два полностью отделить методы которые просто имеют один и тот же идентификатор. Дело в том, что super.touchMe относится к другому методу, чем touchMe, потому что Boom.Inner.touchMeтениBoom.touchMe (и не потому, что он переопределяет он.)

это можно продемонстрировать несколькими способами:

  • как вы сами обнаружили, если вы измените методы на общедоступные, компилятор будет жаловаться, потому что вы are внезапно пытается переопределить окончательный метод.

  • если вы сохраняете методы частными и добавляете @Override аннотация, компилятор будет жаловаться.

  • как альпийские очки, если вы разыгрываете Boom.Inner объекта

Я думаю, что тот факт, что здесь действительно есть два отдельных метода, хорошо продемонстрирован, изменив ваш основной следующим образом:

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 как это в одном классе.

частные методы невидимы для подклассов или любого другого класса, поэтому они могут иметь одно и то же имя, но не перекрывают друг друга.

попробуйте добавить аннотацию @override - вы получите ошибку компилятора.

вы можете переопределить метод, потому что он является private для каждого класса.

вы только что объявили другой метод с тем же именем. Вы можете вызвать частный член класса, потому что внутренний класс сам является членом класса. Надеюсь, что эта модификация объяснит это подробно.

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!