J'ai joué avec des modificateurs avec une méthode statique et je 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 se 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 à la méthode statique dans la classe A, alors la compilation échoue ts () dans B ne peut pas remplacer ts () dans A; la méthode remplacée est statique final .
Pourquoi cela se produit-il lorsque la méthode statique ne peut pas du tout être remplacée?
Réponses:
Les méthodes statiques ne peuvent pas être remplacées mais elles peuvent être masquées. La
ts()
méthode de B ne remplace pas (non sujette au polymorphisme) lats()
de A mais elle le cachera. Si vous appelezts()
en B (PASA.ts()
ouB.ts()
... justets()
), celui de B sera appelé et non A. Comme il n'est pas soumis au polymorphisme, l'appelts()
en A ne sera jamais redirigé vers celui de B.Le mot
final
- clé désactivera le masquage de la méthode. Ils ne peuvent donc pas être masqués et une tentative de le faire entraînera une erreur du compilateur.J'espère que cela t'aides.
la source
A#ts
c'est hérité et qu'une telle méthode existe déjàB
, avoir simplement deux méthodes avec la même signature et un modificateur différent (final
) ne fonctionnerait pas comme des surcharges .. . J'aimerais pouvoir penser à un message simple pour cela, cependantCe n'est pas tout à fait vrai. L'exemple de code signifie vraiment que la méthode ts dans B masque la méthode ts dans A. Donc, ce n'est pas exactement la substitution. Sur Javaranch, il y a une belle explication.
la source
Les méthodes statiques appartiennent à la classe, pas à l'instance.
A.ts()
etB.ts()
seront toujours des méthodes distinctes.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 parent sont masquées lorsqu'elles sont appelées depuis une instance de la sous-classe. Cependant, vous ne pouvez pas remplacer / masquer les méthodes finales .
Vous penseriez que le message d'erreur utiliserait le mot caché au lieu de remplacé ...
la source
Vous pourriez vous trouver en position de penser à rendre une méthode statique définitive, compte tenu des éléments suivants:
Avoir les classes suivantes:
Maintenant, la manière `` correcte '' d'appeler ces méthodes serait
ce qui entraînerait
AB
mais vous pourriez également appeler les méthodes sur les instances:ce qui en résulterait
AB
également.Considérez maintenant ce qui suit:
cela imprimerait
A
. Cela pourrait vous surprendre puisque vous avez en fait un objet de classeB
. Mais puisque vous l'appelez à partir d'une référence de typeA
, il appelleraA.ts()
. Vous pouvez imprimerB
avec le code suivant:Dans les deux cas, l'objet que vous avez est en fait de la classe
B
. Mais selon le pointeur qui pointe vers l'objet, vous appellerez la méthode fromA
ou fromB
.Disons maintenant que vous êtes le développeur de la classe
A
et que vous souhaitez autoriser le sous-classement. Mais vous voulez vraiment que la méthodets()
, chaque fois qu'elle est appelée, même à partir d'une sous-classe, fasse ce que vous voulez qu'elle fasse et ne soit pas masquée par une version de sous-classe. Ensuite, vous pouvez le créerfinal
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 à partir de votre classeA
:Ok, admettre que c'est en quelque sorte construit, mais cela peut avoir du sens dans certains cas.
Vous ne devez pas appeler de méthodes statiques sur les instances mais directement sur les classes - alors vous n'aurez pas ce problème. IntelliJ IDEA, par exemple, vous montrera également un avertissement, si vous appelez une méthode statique sur une instance et aussi si vous rendez une méthode statique définitive.
la source
La méthode ts () dans B ne remplace 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 détectera qu'il existe une méthode ts () dans A qui ne devrait pas être remplacée dans B.
la source
Je pense que l'erreur de compilation était assez trompeuse ici. Il n'aurait pas dû dire «la méthode surchargée est finale statique», mais il aurait dû plutôt dire «la méthode surchargée est définitive». Le modificateur statique n'est pas pertinent ici.
la source
Une méthode statique ne peut pas être remplacée en Java, contrairement aux méthodes non statiques. Mais ils sont hérités 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
Le
final
mot clé garantit que le corps de la méthode spécifique sera exécuté à chaque fois qu'un appel à la méthode. Maintenant, si une méthode statique est créée dans la classe enfant avec le même nom et qu'un appel à la méthode est effectué, la méthode de la sous-classe est exécutée, ce qui ne devrait pas être le cas si final est préfixé avant le nom de la méthode statique dans la classe parent . Par conséquent, le mot-clé final limite la création d'une méthode avec le même nom dans la classe enfant.la source