web-dev-qa-db-fra.com

Comportement de la méthode statique finale

J'ai joué avec des modificateurs avec une méthode statique et suis tombé sur un comportement étrange.

Comme nous le savons, les méthodes statiques ne peuvent pas être remplacées, car elles sont associées à une classe plutôt qu’à une instance.

Donc, si j'ai l'extrait ci-dessous, il compile bien

//Snippet 1 - Compiles fine
public class A {
    static void ts() {
    }
}

class B extends A {
    static void ts() {
    }
}

Mais si j'inclus le modificateur final dans la méthode statique dans la classe A, la compilation échouerats () dans B ne peut pas remplacer ts () dans A; La méthode surchargée est static final.

Pourquoi cela se produit-il lorsque la méthode statique ne peut pas être remplacée?

107
Harish

Les méthodes statiques ne peuvent pas être remplacées mais elles peuvent être masquées. La méthode ts() de B n'empêche pas (non sujette au polymorphisme) la ts() de A mais elle le cachera. Si vous appelez ts() en B (NOT A.ts() ou B.ts() ... juste ts()), celui de B sera appelé et non A. Comme il n'est pas soumis au polymorphisme, l'appel ts() en A ne sera jamais redirigé vers celui de B.

Le mot clé final désactive le masquage de la méthode. Ils ne peuvent donc pas être masqués et une tentative dans ce but entraînera une erreur du compilateur.

J'espère que cela t'aides.

146
NawaMan

les méthodes statiques ne peuvent pas être remplacées

Ce n'est pas tout à fait vrai. L'exemple de code signifie réellement que la méthode ts dans B cache la méthode ts dans A. Donc, ce n'est pas exactement prioritaire. Sur Javaranch il y a une bonne explication.

11
Vincent Ramdhanie

Les méthodes statiques appartiennent à la classe, pas à l'instance.

A.ts() et B.ts() seront toujours des méthodes séparées.

Le vrai problème est que Java vous permet d'appeler des méthodes statiques sur un objet d'instance. Les méthodes statiques avec la même signature de la classe parente sont hidden lorsqu'elles sont appelées à partir d'une instance de la sous-classe. Cependant, vous ne pouvez pas remplacer/cacher méthodes finales .

Vous penseriez que le message d'erreur utiliserait le mot caché au lieu de remplacer ...

9
Powerlord

Vous pourriez vous trouver en position de penser à rendre une méthode statique finale, en tenant compte de ce qui suit:

Ayant les classes suivantes:

class A {
    static void ts() {
        System.out.print("A");
    }
}
class B extends A {
    static void ts() {
        System.out.print("B");
    }
}

Maintenant, la façon «correcte» d'appeler ces méthodes serait

A.ts();
B.ts();

ce qui aurait pour résultat AB mais vous pouvez également appeler les méthodes sur des instances:

A a = new A();
a.ts();
B b = new B();
b.ts();

ce qui aurait pour résultat AB également.

Considérons maintenant ce qui suit:

A a = new B();
a.ts();

cela afficherait A. Cela pourrait vous surprendre puisque vous rencontrez un objet de classe B. Mais puisque vous l'appelez à partir d'une référence de type A, il appellera A.ts(). Vous pouvez imprimer B avec le code suivant:

A a = new B();
((B)a).ts();

Dans les deux cas, l'objet que vous avez provient de la classe B. Mais selon le pointeur qui pointe sur l'objet, vous appellerez la méthode de A ou de B

Supposons maintenant que vous êtes le développeur de la classe A et que vous souhaitez autoriser le sous-classement. Mais vous voulez vraiment la méthode ts(), chaque fois appelée, même à partir d'une sous-classe, c'est ce que vous voulez qu'elle fasse et ne pas être cachée par une version de sous-classe. Ensuite, vous pouvez le rendre final et l'empêcher d'être caché dans la sous-classe. Et vous pouvez être sûr que le code suivant appellera la méthode de votre classe A:

B b = new B();
b.ts();

D'accord, admittetly est en quelque sorte construit, mais cela pourrait avoir un sens dans certains cas.

Vous ne devez pas appeler des méthodes statiques sur des instances mais directement sur des classes - vous ne rencontrerez alors pas ce problème. Aussi, IntelliJ IDEA par exemple vous montrera un avertissement si vous appelez une méthode statique sur une instance et également si vous rendez une méthode statique finale.

5
Mathias Bader

Je pense que l'erreur de compilation était assez trompeuse ici. Il n'aurait pas dû dire "la méthode surchargée est statique finale", mais au lieu de "la méthode surchargée est finale" Le modificateur statique est sans importance ici.

1
BalusC

Une méthode statique ne peut pas être remplacée en Java, contrairement aux méthodes non statiques . Mais elles sont héritées comme des membres de données statiques et non statiques. C'est pourquoi une méthode non statique avec le même nom ne peut pas être créée dans la classe parente

class Writer { 
    public static void doo(){
        System.out.println("sth");
    } 
}
class Author extends Writer{ 
    public void doo(){
        System.out.println("ok"); // error overridden method is static
    }
}

Le mot clé final garantit que le corps de la méthode spécifique est exécuté à chaque appel de la méthode . Désormais, si une méthode statique est créée dans la classe enfant avec le même nom et que l'appel de la méthode est effectué, la méthode de la sous-classe est exécuté, ce qui ne devrait pas être le cas si final est préfixé avant le nom de la méthode statique dans la classe parente. Ainsi, le mot-clé final limite la création de méthodes avec le même nom dans la classe enfant.

0
Pratik Gupta

La méthode ts () dans B n’annule pas la méthode ts () dans A, c’est simplement une autre méthode. La classe B ne voit pas la méthode ts () dans A car elle est statique, elle peut donc déclarer sa propre méthode appelée ts ().

Cependant, si la méthode est finale, le compilateur remarquera qu'il existe une méthode ts () dans A qui ne devrait pas être remplacée dans B.

0
amischiefr