Je fais actuellement un devoir pour l'une de mes classes, et dans celui-ci, je dois donner des exemples, en utilisant la syntaxe Java, de liaison statique et dynamique .
Je comprends le concept de base, que la liaison statique se produit au moment de la compilation et la liaison dynamique se produit au moment de l'exécution, mais je ne peux pas comprendre comment elles fonctionnent réellement.
J'ai trouvé un exemple de liaison statique en ligne qui donne cet exemple:
public static void callEat(Animal animal) {
System.out.println("Animal is eating");
}
public static void callEat(Dog dog) {
System.out.println("Dog is eating");
}
public static void main(String args[])
{
Animal a = new Dog();
callEat(a);
}
Et que cela afficherait "l'animal mange" parce que l'appel à callEat
utilise la liaison statique , mais je ne suis pas sûr de savoir pourquoi cela est considéré comme une liaison statique.
Jusqu'à présent, aucune des sources que j'ai vues n'a réussi à expliquer cela d'une manière que je puisse suivre.
la source
Réponses:
De l' article de blog Javarevisited :
la source
La connexion d'un appel de méthode au corps de la méthode est connue sous le nom de Binding. Comme l'a dit Maulik, «la liaison statique utilise les informations de type (classe en Java) pour la liaison, tandis que la liaison dynamique utilise Object pour résoudre la liaison». Donc ce code:
Produira le résultat: le chien mange ... car il utilise la référence d'objet pour trouver la méthode à utiliser. Si nous changeons le code ci-dessus en ceci:
Il produira: animal mange ... parce que c'est une méthode statique, il utilise donc Type (dans ce cas Animal) pour déterminer quelle méthode statique appeler. Outre les méthodes statiques, les méthodes privées et finales utilisent la même approche.
la source
a
s'agit en fait d'unDog
au moment de la compilation?Le compilateur sait seulement que le type de "a" est
Animal
; cela se produit au moment de la compilation, à cause de quoi il est appelé liaison statique (surcharge de méthode). Mais s'il s'agit d'une liaison dynamique, il appellerait laDog
méthode de classe. Voici un exemple de liaison dynamique.Sortie: Méthode de manger à l'intérieur du chien
la source
Eh bien, afin de comprendre comment la liaison statique et dynamique fonctionne réellement la ? ou comment ils sont identifiés par le compilateur et JVM?
Prenons l'exemple ci-dessous où se
Mammal
trouve une classe parente qui a une méthodespeak()
et uneHuman
classe étendMammal
, remplace laspeak()
méthode et la surcharge à nouveauspeak(String language)
.Lorsque nous compilons le code ci-dessus et essayons de regarder le bytecode en utilisant
javap -verbose OverridingInternalExample
, nous pouvons voir que le compilateur génère une table constante où il affecte des codes entiers à chaque appel de méthode et code d'octet pour le programme que j'ai extrait et inclus dans le programme lui-même ( voir les commentaires ci-dessous chaque appel de méthode)En regardant le code ci - dessus , nous pouvons voir que le bytecode de
humanMammal.speak()
,human.speak()
ethuman.speak("Hindi")
sont totalement différents (invokevirtual #4
,invokevirtual #7
,invokevirtual #9
) parce que le compilateur est capable de faire la différence entre eux en fonction de la liste des arguments et référence de classe. Parce que tout cela est résolu au moment de la compilation de manière statique, c'est pourquoi la surcharge de méthode est connue sous le nom de polymorphisme statique ou statique liaison statique .Mais bytecode pour
anyMammal.speak()
ethumanMammal.speak()
est identique (invokevirtual #4
) car selon le compilateur les deux méthodes sont appeléesMammal
référence.Alors maintenant, la question se pose si les deux appels de méthode ont le même bytecode, comment JVM sait-elle quelle méthode appeler?
Eh bien, la réponse est cachée dans le bytecode lui-même et c'est
invokevirtual
un jeu d'instructions. JVM utilise leinvokevirtual
instruction pour appeler l'équivalent Java des méthodes virtuelles C ++. En C ++, si nous voulons remplacer une méthode dans une autre classe, nous devons la déclarer comme virtuelle, mais en Java, toutes les méthodes sont virtuelles par défaut car nous pouvons remplacer toutes les méthodes de la classe enfant (à l'exception des méthodes privées, finales et statiques).En Java, chaque variable de référence contient deux pointeurs cachés
Ainsi, toutes les références d'objet contiennent indirectement une référence à une table qui contient toutes les références de méthode de cet objet. Java a emprunté ce concept à C ++ et cette table est connue sous le nom de table virtuelle (vtable).
Une vtable est une structure de type tableau qui contient les noms de méthodes virtuelles et leurs références sur les index de tableau. JVM crée une seule vtable par classe lorsqu'elle charge la classe en mémoire.
Ainsi, chaque fois que JVM rencontre un
invokevirtual
jeu d'instructions, il vérifie la vtable de cette classe pour la référence de méthode et invoque la méthode spécifique qui, dans notre cas, est la méthode d'un objet et non la référence.Parce que tout cela est résolu au moment de l'exécution uniquement et au moment de l'exécution, la JVM sait quelle méthode appeler, c'est pourquoi le remplacement de méthode est connu sous le nom de polymorphisme dynamique ou simplement de polymorphisme ou de liaison dynamique. .
Vous pouvez le lire plus en détail sur mon article Comment la JVM gère-t-elle la surcharge et le remplacement de méthode en interne .
la source
Il existe trois différences majeures entre la liaison statique et dynamique lors de la conception des compilateurs et la manière dont les variables et les procédures sont transférées vers l' environnement d' exécution . Ces différences sont les suivantes:
Liaison statique : dans la liaison statique, trois problèmes suivants sont abordés:
Définition d'une procédure
Déclaration d'un nom (variable, etc.)
Portée de la déclaration
Liaison dynamique : trois problèmes rencontrés dans la liaison dynamique sont les suivants:
Activation d'une procédure
Liaison d'un nom
Durée de vie d'une reliure
la source
Avec la méthode statique dans la classe parent et enfant: liaison statique
Liaison dynamique:
la source
Toutes les réponses ici sont correctes mais je veux ajouter quelque chose qui manque. lorsque vous surchargez une méthode statique, il semble que nous la surchargions, mais en réalité ce n'est pas une substitution de méthode. Au lieu de cela, il est appelé masquage de méthode. Les méthodes statiques ne peuvent pas être remplacées en Java.
Regardez l'exemple ci-dessous:
Dans la liaison dynamique, la méthode est appelée en fonction du type de référence et non du type d'objet que la variable de référence contient. Ici, la liaison statique se produit car le masquage de méthode n'est pas un polymorphisme dynamique. Si vous supprimez le mot-clé static devant eat () et en faites une méthode non statique, cela vous montrera un polymorphisme dynamique et non un masquage de méthode.
J'ai trouvé le lien ci-dessous pour soutenir ma réponse: https://youtu.be/tNgZpn7AeP0
la source
Dans le cas du type d'objet de liaison statique déterminé au moment de la compilation, tandis que dans le cas du type de liaison dynamique de l'objet est déterminé au moment de l'exécution.
la source
Parce que le compilateur connaît la liaison au moment de la compilation. Si vous invoquez une méthode sur une interface, par exemple, le compilateur ne peut pas le savoir et la liaison est résolue au moment de l'exécution car l'objet réel sur lequel une méthode est invoquée pourrait être l'un de plusieurs. Par conséquent, il s'agit du runtime ou de la liaison dynamique.
Votre appel est lié à la classe Animal au moment de la compilation car vous avez spécifié le type. Si vous passiez cette variable dans une autre méthode ailleurs, personne ne saurait (à part vous parce que vous l'avez écrite) de quelle classe il s'agirait. Le seul indice est le type d'animal déclaré.
la source