Почему компилятор не жалуется, когда я пытаюсь переопределить статический метод?

Я знаю, что мы не можем переопределять статические методы в 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();

означает, что статический класс нельзя переопределить если он будет переопределен, то как это сделать.