web-dev-qa-db-fra.com

Pourquoi le compilateur ne se plaint-il pas lorsque j'essaie de remplacer une méthode statique?

Je sais que nous ne pouvons pas remplacer les méthodes statiques en Java, mais quelqu'un peut-il expliquer le code suivant?

class A {
    public static void a() { 
        System.out.println("A.a()");
    }
}   

class B extends A {
    public static void a() {
        System.out.println("B.a()");
    }
}

Comment ai-je pu remplacer la méthode a() dans la classe B?

34
user2395360

Vous n'avez rien ignoré ici. Pour voir par vous-même, essayez de mettre l'annotation @Override Avant public static void a() dans la classe B et Java générera une erreur.

Vous venez de définir une fonction dans la classe B appelée a(), qui est distincte (sans aucune relation) de la fonction a() dans la classe A.

Mais comme B.a() a le même nom qu'une fonction de la classe parente, elle cache A.a() [As pointé par l'ing. Fouad]. Au moment de l'exécution, le compilateur utilise la classe réelle de la référence déclarée pour déterminer la méthode à exécuter. Par exemple,

B b = new B();
b.a() //prints B.a()

A a = (A)b;
a.a() //print A.a(). Uses the declared reference's class to find the method.

Vous ne pouvez pas remplacer les méthodes statiques en Java. N'oubliez pas que les méthodes et les champs static sont associés à la classe et non aux objets. (Bien que, dans certaines langues comme Smalltalk, cela soit possible).

J'ai trouvé de bonnes réponses ici: Pourquoi Java ne permet pas de remplacer les méthodes statiques?

54
goblinjuice

Cela s'appelle hiding a method, comme indiqué dans le Java tutorial Overriding and Hiding Methods :

Si une sous-classe définit une méthode de classe avec la même signature qu'une méthode de classe dans la superclasse, la méthode dans la sous-classe masque celle de la superclasse.

9
Eng.Fouad

Les méthodes static ne sont pas héritées, donc la copie séparée de la méthode de son B

static sont liés à class et non à l'état de Object

6
Jigar Joshi

Vous n'avez pas remplacé la méthode a(), car les méthodes static ne sont pas héritées. Si vous aviez mis @Override, vous auriez vu une erreur.

A.Java:10: error: method does not override or implement a method from a supertype
    @Override
    ^
1 error

Mais cela ne vous empêche pas de définir des méthodes statiques avec la même signature dans les deux classes.

3
rgettman

De plus, le choix de la méthode à appeler dépend du type déclaré de la variable.

B b = null;
b.a(); // (1) prints B.a()
A a = new B();
a.a(); // (2) prints a.a() 

En (1), si le système se souciait de l'identité de b, il lancerait un NPE. et en (2), la valeur de a est ignorée. Puisque a est déclaré comme A, A.a() est appelé.

2
Eric Jablow

Votre méthode n'est pas une méthode remplacée. vous essayez simplement de mettre l'annotation @Override avant votre méthode dans la classe dérivée. cela vous donnera une erreur de temps de compilation. donc Java ne vous permettra pas de remplacer la méthode statique.

1
user1374185

Bien que la réponse goblinjuice ait été acceptée, je pensais que l'exemple de code pourrait être amélioré:

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");
    }
}

Produit:

A
B
-
A
B
-
A

Si B avait remplacé print(), il aurait écrit B sur la dernière ligne.

1
David Newcomb

Les méthodes statiques seront appelées par son nom de classe, nous n'avons donc pas besoin de créer d'objet de classe, nous l'appelons simplement avec le nom de classe afin que nous ne puissions pas remplacer statique

par exemple

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
}
}

nous l'appelons simplement

AClass.test();

signifie que la classe statique ne peut pas être remplacée si elle est remplacée, alors comment l'appeler.

0
javaCode555