Pourquoi y a-t-il une méthode par défaut?
Java 8 arrive. Comme mentionné précédemment, nous avons beaucoup discuté de ce thème auparavant, mais l'expression de Lambdas n'est pas le seul changement de règles de jeu dans Java 8.
Supposons que Java 8 ait été libéré et contient du lambda. Vous prévoyez maintenant d'utiliser Lambda.
List <?> List = ... list.faceach (…);
La définition de ForEach ne peut être trouvée dans java.util.list ou java.util.collection. Il s'agit généralement d'une solution pour ajouter de nouvelles méthodes et implémentations aux interfaces pertinentes dans JDK. Cependant, pour la version de la version, il est impossible d'ajouter une nouvelle méthode à l'interface sans affecter l'implémentation existante.
Par conséquent, si la lambda est utilisée dans Java 8, il n'est pas possible d'être utilisé pour la bibliothèque de collecte en raison de la compatibilité directe.
Pour les raisons ci-dessus, un nouveau concept a été introduit. La méthode d'extension virtuelle, qui est généralement la méthode de défense, peut désormais être ajoutée à l'interface, de sorte que l'implémentation par défaut du comportement de l'instruction peut être fournie.
Autrement dit, l'interface Java peut désormais implémenter la méthode. L'avantage de la méthode par défaut est qu'il peut ajouter une nouvelle méthode par défaut à l'interface sans détruire l'implémentation de l'interface.
À mon avis, ce n'est pas le type de caractéristique Java qui sera utilisé tous les jours, mais il peut certainement utiliser Lambda pour utiliser Lambda naturellement.
L'exemple le plus simple
Voyons l'exemple le plus simple: une interface A, la classe Clazz implémente l'interface A.
Interface publique a {par défaut void foo () {System.out.println ("appelant a.foo ()");} classe publique classe de classe A {}Le code peut être compilé, même si la classe Clazz n'implémente pas la méthode foo (). L'implémentation par défaut de la méthode foo () est fournie dans l'interface A.
Code client en utilisant cet exemple:
Clazz Clazz = New Clazz ();
Héritage multiple?
Il y a une question courante: les gens se demandent quand ils entendent les nouvelles fonctionnalités de la méthode par défaut "" Si une classe met en œuvre deux interfaces, et les deux interfaces définissent la méthode par défaut avec la même signature. avec des exemples précédents:
Interface publique a {par défaut void foo () {System.out.println ("appelant a.foo ()");Ce code ne peut pas compiler les raisons suivantes:
Java: Class Clazz des types A à B à Foo () hérite de la valeur par défaut non apparentée
Afin de réparer cela, dans Clazz, nous devons résoudre manuellement la méthode de réécriture du conflit:
Classe publique Clazz implémente a, b {public void foo () {}}} Mais que devons-nous faire si nous voulons appeler la méthode d'implémentation par défaut à partir de l'interface A, au lieu d'implémenter notre propre méthode? Ceci est possible, citez le foo () dans A, comme indiqué ci-dessous:
Classe publique Clazz implémente a, b {public void foo () {a.super.foo ();}}} Maintenant, je ne peux pas être très convaincu que j'aime cette solution finale. Il est peut-être plus concis que la réalisation de la méthode par défaut dans la signature, comme indiqué dans le projet de première main de la spécification de la méthode par défaut:
Classe publique Clazz implémente a, b {public void foo () par défaut a.foo;}Mais cela change la grammaire, n'est-ce pas? Si l'interface A et l'interface B définissent de nombreuses méthodes par défaut qui entrent en conflit les uns avec les autres, et je suis prêt à utiliser la méthode par défaut de toute l'interface A pour résoudre le conflit? À l'heure actuelle, je dois résoudre le conflit l'un après l'autre pour réécrire chaque paire de conflits. Cela peut nécessiter beaucoup de travail et écrire un grand nombre de code de modèle.
J'estime que la méthode de résolution du conflit nécessite de nombreuses discussions, mais il semble que le créateur décide d'accepter la catastrophe inévitable.
Vrai exemple
Les vrais exemples de la méthode par défaut se trouvent dans le premier sac de JDK8. Retour à l'exemple de la méthode de collection de la collection, nous pouvons constater que dans l'interface java.lang.iterable, son implémentation par défaut est la suivante:
@FunctionalInterfacePublic Inteable <T> {Iterator <T> Iterator (); ForEach utilise un paramètre de java.util.function.consumer le type d'interface de fonction, qui nous permet de passer une expression de lambda ou une référence de méthode, comme suit:
List <?> List = ... list.faceach (System.out :: println);
Appel de méthode
Jetons un coup d'œil à la façon dont la méthode par défaut est réellement appelée. Si vous n'êtes pas familier avec ce problème, vous pourriez être intéressé à lire les laboratoires rebelles sur les octets Java.
Du point de vue du code client, la méthode par défaut n'est qu'une méthode virtuelle courante. Par conséquent, le nom doit être une méthode d'extension virtuelle. Par conséquent, pour un exemple simple de la méthode par défaut en tant qu'interface, le code client appellera automatiquement l'interface à l'endroit où la méthode par défaut est appelée.
A Clazz = New Clazz (); Clazz.foo ();
Si le conflit de la méthode par défaut a été résolu, lorsque nous modifions la méthode par défaut et spécifions l'une des interfaces, InvokeSpecial spécifiera l'implémentation de quelle interface implémentation de l'appel spécifique.
Classe publique Clazz implémente a, b {public void foo () {a.super.foo (); Ce qui suit est la sortie de Javap:
public void foo (); Code: 0: ALOAD_01: InvokeSpecial # 2 // InterfaceMethod
Comme vous le voyez: les instructions InvokeSpecial sont utilisées pour appeler la méthode d'interface FOO (). Du point de vue de ByteCode, c'est encore une nouvelle chose, car avant de ne pouvoir appeler la méthode qu'en pointant une classe (parent) au lieu d'un super point vers une interface.
enfin…
La méthode par défaut est le complément intéressant de la langue Java. L'objectif principal de l'expression par défaut est d'évoluer l'interface JDK standard, et lorsque nous commençons enfin à utiliser l'expression Lambdas de Java 8, nous nous offrons une expérience de transition en douceur. Qui sait, peut-être que nous verrons plus de méthodes par défaut dans la conception de l'API à l'avenir.