Я задавался вопросом, имеет ли смысл объявлять частный метод как окончательный, и я думал, что это не имеет смысла. Но я представил себе исключительную ситуацию и написал код, чтобы понять это:
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!
почему?
Ответ 1
Частные методы не могут быть переопределены (частные методы не наследуются!) На самом деле, не имеет значения, если вы объявляете закрытый метод final или нет.
Два метода, которые вы указали, Boom.touchMe
и Boom.Inner.touchMe
- это два полностью отдельных метода, которые просто имеют один и тот же идентификатор. Тот факт, что super.touchMe
относится к другому методу, чем touchMe
, заключается только в том, что Boom.Inner.touchMe
shadows Boom.touchMe
(а не потому, что он переопределяет его).
Это можно продемонстрировать несколькими способами:
-
Как вы обнаружили, если вы измените методы, которые будут публичными, компилятор будет жаловаться, потому что вы вдруг пытаетесь переопределить окончательный метод.
-
Если вы сохраните методы private и добавьте аннотацию @Override
, компилятор будет жаловаться.
-
Как указывает альпинист, если вы нажмете объект Boom.Inner
на объект Boom
(((Boom) inner).touchMe()
), вызывается Boom.touchMe
(если он действительно был переопределен, приведение не имеет значения).
Связанный вопрос:
Ответ 2
Я думаю, что факт, что на самом деле существуют два отдельных метода, хорошо продемонстрирован, изменив ваш основной принцип следующим образом:
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
как он находится в одном классе.
Ответ 3
Частные методы невидимы для подклассов или даже для любого другого класса, поэтому они могут иметь одно и то же имя, но не переуступать друг друга.
Попробуйте добавить аннотацию @Override - вы получите ошибку компилятора.
Ответ 4
Вы можете переопределить метод, потому что он private
для каждого класса.
Ответ 5
Вы только что объявили другой метод с тем же именем. Вы можете вызвать частный член класса, потому что внутренний класс сам является членом класса. Надеюсь, что эта модификация подробно объяснит это.
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!