Почему внутренний класс может переопределить 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 ответов:
частные методы не могут быть переопределены (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 - вы получите ошибку компилятора.
вы только что объявили другой метод с тем же именем. Вы можете вызвать частный член класса, потому что внутренний класс сам является членом класса. Надеюсь, что эта модификация объяснит это подробно.
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!