Liaison statique et dynamique en Java

1. Introduction

Le polymorphisme permet à un objet de prendre plusieurs formes - lorsqu'une méthode présente un polymorphisme, le compilateur doit mapper le nom de la méthode sur l'implémentation finale.

S'il est mappé au moment de la compilation, il s'agit d'une liaison statique ou anticipée.

S'il est résolu au moment de l'exécution, il s'agit d'une liaison dynamique ou tardive.

2. Comprendre grâce à un code

Lorsqu'une sous-classe étend une superclasse, elle peut réimplémenter les méthodes qu'elle définit. C'est ce qu'on appelle un remplacement de méthode.

Par exemple, créons un animal de superclasse :

public class Animal { static Logger logger = LoggerFactory.getLogger(Animal.class); public void makeNoise() { logger.info("generic animal noise"); } public void makeNoise(Integer repetitions) { while(repetitions != 0) { logger.info("generic animal noise countdown " + repetitions); repetitions -= 1; } } }

Et un chien de sous-classe :

public class Dog extends Animal { static Logger logger = LoggerFactory.getLogger(Dog.class); @Override public void makeNoise() { logger.info("woof woof!"); } }

En cas de surcharge d'une méthode, comme le makeNoise () de la classe Animal , le compilateur résoudra la méthode et son code au moment de la compilation. Ceci est un exemple de liaison statique.

Cependant, si nous affectons un objet de type Dog à une référence de type Animal , le compilateur résoudra le mappage de code de fonction lors de l'exécution. C'est une liaison dynamique.

Pour comprendre comment cela fonctionne, écrivons un petit extrait de code pour appeler les classes et ses méthodes:

Animal animal = new Animal(); // calling methods of animal object animal.makeNoise(); animal.makeNoise(3); // assigning a dog object to reference of type Animal Animal dogAnimal = new Dog(); dogAnimal.makeNoise(); The output of the above code will be:
com.baeldung.binding.Animal - generic animal noise com.baeldung.binding.Animal - generic animal noise countdown 3 com.baeldung.binding.Animal - generic animal noise countdown 2 com.baeldung.binding.Animal - generic animal noise countdown 1 com.baeldung.binding.Dog - woof woof!

Maintenant, créons une classe:

class AnimalActivity { public static void eat(Animal animal) { System.out.println("Animal is eating"); } public static void eat(Dog dog) { System.out.println("Dog is eating"); } }

Ajoutons ces lignes à la classe principale:

AnimalActivity.eat(dogAnimal);

Le résultat serait:

com.baeldung.binding.AnimalActivity - Animal is eating

Cet exemple montre qu'une fonction statique subit une liaison statique .

La raison en est que les sous-classes ne peuvent pas remplacer les méthodes statiques. Si la sous-classe implémentait la même méthode, elle masquerait la méthode de la superclasse. De même, si une méthode est finale ou privée, la JVM effectuera une liaison statique.

Une méthode statique liée n'est pas associée à un objet particulier mais est plutôt appelée sur Type (classe en Java). L'exécution d'une telle méthode est légèrement plus rapide.

Toute autre méthode est automatiquement une méthode virtuelle en Java par défaut. La JVM résout ces méthodes lors de l'exécution et il s'agit d'une liaison dynamique.

L'implémentation exacte dépend de la JVM, mais elle prendrait une approche de type C ++, où la JVM recherche la table virtuelle pour décider sur quel objet la méthode sera appelée.

3. Conclusion

La liaison fait partie intégrante d'un langage qui implémente le polymorphisme, il est important de comprendre les implications de la liaison statique et dynamique pour être sûr que nos applications se comportent comme nous le souhaitons.

Avec cette compréhension, cependant, nous sommes en mesure d'utiliser efficacement l'héritage de classe ainsi que la surcharge de méthode.

Comme toujours, le code est disponible sur sur GitHub.