Почему компилятор не жалуется, когда я пытаюсь переопределить статический метод?
Я знаю, что мы не можем переопределять статические методы в Java, но может кто-нибудь объяснить следующий код?
class A {
public static void a() {
System.out.println("A.a()");
}
}
class B extends A {
public static void a() {
System.out.println("B.a()");
}
}
Как мне удалось переопределить метод a()
в классе B
?
Ответы
Ответ 1
Вы ничего здесь не отменяли. Чтобы убедиться в этом, попробуйте помечать аннотацию @Override
до public static void a()
в классе B
, а Java выдает ошибку.
Вы только что определили функцию в классе B
, называемую a()
, которая отличается (не имеет никакого отношения) от функции a()
в классе A
.
Но поскольку B.a()
имеет то же имя, что и функция в родительском классе, он скрывает A.a()
[Как указано в Eng. Фуад]. Во время выполнения компилятор использует фактический класс объявленной ссылки для определения того, какой метод запускать. Например,
B b = new B();
b.a() //prints B.a()
A a = (A)b;
a.a() //print A.a(). Uses the declared reference class to find the method.
Вы не можете переопределять статические методы в Java. Помните static
методы и поля связаны с классом, а не с объектами. (Хотя, на некоторых языках, таких как Smalltalk, это возможно).
Я нашел несколько хороших ответов здесь: Почему Java не позволяет переопределять статические методы?
Ответ 2
Это называется hiding a method
, как указано в учебнике Java Переопределение и скрытие методов:
Если подкласс определяет метод класса с той же сигнатурой, что и метод класса в суперклассе, метод в подклассе скрывает один в суперклассе.
Ответ 3
static
методы не наследуются, поэтому его B
отдельная копия метода
static
связаны с class
не состоянием Object
Ответ 4
Вы не переопределили метод a()
, потому что методы static
не наследуются. Если вы положили @Override
, вы бы увидели ошибку.
A.java:10: error: method does not override or implement a method from a supertype
@Override
^
1 error
Но это не мешает вам определять статические методы с одинаковой сигнатурой в обоих классах.
Ответ 5
Кроме того, выбор метода для вызова зависит от объявленного типа переменной.
B b = null;
b.a(); // (1) prints B.a()
A a = new B();
a.a(); // (2) prints a.a()
В (1), если система заботилась об идентичности b
, она выбрала бы NPE
. и при (2) значение a
игнорируется. Поскольку a
объявлен как a
, вызывается A.a()
.
Ответ 6
Ваш метод не переопределяется. вы просто пытаетесь поставить аннотацию @Override перед вашим методом в производном классе. это даст вам ошибку времени компиляции. поэтому java не позволит вам переопределить статический метод.
Ответ 7
В то время как ответ goblinjuice был принят, я подумал, что пример кода может быть улучшен:
public class StaticTest {
public static void main(String[] args) {
A.print();
B.print();
System.out.println("-");
A a = new A();
B b = new B();
a.print();
b.print();
System.out.println("-");
A c = b;
c.print();
}
}
class A {
public static void print() {
System.out.println("A");
}
}
class B extends A {
public static void print() {
System.out.println("B");
}
}
Выдает:
A
B
-
A
B
-
A
Если B переопределил print()
, он бы записал B в последней строке.
Ответ 8
Статические методы вызывают по его имени класса, поэтому нам не нужно создавать объект класса, просто укажем его с именем класса, чтобы мы не могли переопределить статические
например
class AClass{
public static void test(){
}
}
class BClass extends AClass{
public static void test(){}
}
class CClass extends BClass{
public static void main(String args[]){
AClass aclass=new AClass();
aclass.test(); // its wrong because static method is called
// by its class name it can't accept object
}
}
мы просто называем это
AClass.test();
означает, что статический класс нельзя переопределить
если он будет переопределен, то как это сделать.