Java 8 a commencé à apparaître, apportant une nouvelle fonctionnalité: utilisez l'expression de Lambda (JSR-335) pour la programmation fonctionnelle. Aujourd'hui, nous allons discuter d'une partie de Lambda: Extension virtuelle, également connue sous le nom de méthode Defender. Cette fonctionnalité vous permet d'implémenter la méthode de fourniture de méthodes dans la définition de l'interface. Par exemple, vous pouvez définir une méthode pour les interfaces existantes (telles que la liste et la carte) afin que les autres développeurs n'aient pas besoin de réintégrer ces méthodes, ce qui est un peu comme un abstrait, mais c'est en fait une interface. Bien sûr, Java 8 est théoriquement compatible avec les bibliothèques existantes.
La méthode d'extension virtuelle apporte de multiples caractéristiques de l'héritage à Java. Vous pouvez peut-être voir l'ombre de plusieurs héritage à travers cette fonctionnalité. Mais vous pouvez toujours simuler l'héritage de l'état d'instance. Je décrirai l'héritage de l'État par le mixin dans le prochain article en détail.
Qu'est-ce qui est mélangé en mélange?
Le mélange est une classe abstraite d'une combinaison. Par exemple, si vous avez une classe pour indiquer le "cheval", vous pouvez instancier cette classe pour créer un exemple de "cheval", puis l'étendre en héritant comme "garage" et "jardin".
Val Myhouse = nouvelle maison avec garage avec jardin
D'après l'héritage de mixin n'est pas une spécification spécifique, il s'agit d'une méthode qui est utilisée pour ajouter diverses fonctions aux catégories existantes. Dans OOP, avec Mixin, vous avez la lisibilité de la classe à travers elle.
Par exemple, il existe une méthode de mixin dans le module Socketserver de Python.
Class ForkingPServer (FORKINGMIXIN, UDPSERVER): Passclass ForkingTcPServer (FORKINGMIXIN, TCPSSERVER): Pass Class ThreadingudPServer (ThreadMixin): PassClass ThreadingTcServer (ThreadingMixin, TCPSserver): PassClass
Qu'est-ce qu'une méthode d'extension virtuelle?
Java 8 introduira le concept d'extension virtuelle, également appelée méthode du défenseur public.
VEM vise à fournir la méthode par défaut pour l'interface Java. Une telle bibliothèque de troisième partie comme Hibernate n'a pas besoin de répéter toutes les méthodes de ces API de collecte car elle a fourni certaines méthodes par défaut.
Ce qui suit est un exemple de la façon de définir la méthode dans l'interface:
La collection d'interface publique <T> étend ITable <T> {<r> COLLECTE <R> Filtre (prédicat <T> P) par défaut {return Collections.
Simulation mixte de Java 8
Maintenant, nous arrivons à réaliser un effet mixte via VEM, mais l'avertissement à l'avance est: veuillez ne pas utiliser au travail!
La mise en œuvre suivante n'est pas un fil de discussion, et il peut y avoir un problème de fuite de mémoire, ce qui dépend du HashCode et est égal aux méthodes que vous avez définies dans la classe.
Tout d'abord, nous définissons une définition d'une méthode (haricot d'état simulé) et fournissons la méthode:
Interface publique SwitchableMixin {boolean isActivated () Default {return switchables.isactived (this);} void setActivated (booléen activité) fall {switchables.setAntivated (this, activé);}}
Ensuite, nous définissons une classe d'outils qui contient une instance de carte pour enregistrer l'association des instances et du statut.
Public Final Class Switables {Private Static Final Map <SwitchableMixin, SwitchableDeviceState> switch_states = new hashmap <() (); public static iSactivated (switchableMixin) {switchabledEviceState State = switch_states.get (device); Activité;} public static void setActivated (SwitchableMixin Device, Boolean activé) {SwitchableDeviceState = switch_states.get (périphérique); .Actived = activé;} classe statique privée switchableviceState {privé booléen activé;}}
Voici un cas d'utilisation qui met en évidence l'hérédité de l'État:
Dispositif de classe statique privé {} classe statique privée Devicea étend le périphérique implémente SwitchableMixin {} classe statique privée deviceB étend le périphérique IMP Leater SwitchableMixin {}
"Des choses complètement différentes"
L'implémentation ci-dessus semble normale, mais l'architecte en langue java d'Oracle, Brian Goetz, m'a posé la question que l'implémentation actuelle n'est pas en mesure de travailler (en supposant que la sécurité des fils et la fuite de mémoire ont été résolues)
Interface FakeBrokenMixin {STATIC MAP <FALSEBROKKINGIX, String> BackingMap = Collections. put (this, name);}} l'interface x étend Runnable, FakeBRokenMixin {} x Makex () {return () -> {System.println ("x");}; ();
Quel résultat devinez-vous que ce code sera affiché après l'exécution?
Solution de doute
À première vue, il n'y a aucun problème avec ce code d'implémentation. X est une interface qui ne contient qu'une seule méthode, car GetName et SetName ont déjà la définition par défaut, mais la méthode d'exécution de l'interface gérée n'est pas définie. Implémentation de la méthode d'exécution. Par conséquent, le résultat que vous souhaitez ce programme après l'exécution est:
X1x2
Si vous supprimez l'appel de la méthode GetName, le résultat d'exécution devient:
Mytest 1 $ @ 30ae8764mytest 1 $ @ 123ACF34
Ces deux lignes montrent que l'exécution de la méthode Makex provient de deux instances différentes, et à l'heure actuelle, l'OpenJDK 8 actuel est généré (ici j'utilise OpenJDK 8 24.0-B07).
Dans tous les cas, l'OpenJDK 8 actuel ne reflète pas le comportement final Java 8.
X2x2
Si vous n'appelez pas la méthode getName, elle sera affichée:
MyTest $ $ lambda 1 $ @ 5506d4EamyTest $ Lambda 1 $ @ 5506d4ea
Chaque méthode d'appel Makex semble être une instance simple de la même classe interne anonyme.
Parce que pendant la compilation, l'expression de Lambda n'a pas subi une traduction complète. Cette instruction contient toutes les méta-informations nécessaires sur l'expression de Labda à l'exécution. Y compris le nom de la méthode, le type d'entrée et de sortie, et une méthode appelée bootstrap. La méthode bootstrap est utilisée pour définir l'instance de recevoir cette méthode.
De retour à la question à l'heure actuelle, l'expression de Lambda s'est transformée en une méthode statique privée, () -> {System.out.println ("x");} a été transféré à MyTest:
LAMBDA PRIVÉ STATIQUE PRIVATIVE 0 $ () {System.out.println ("x");}
Si vous utilisez le paramètre privé avec le périphérique de compilation Javap et que vous pouvez voir cette méthode, vous pouvez également utiliser le paramètre -C pour afficher une conversion plus complète.
Lorsque vous exécutez le programme, JVM appelle la méthode Metafactory Lambda pour essayer d'expliquer les instructions invoquées. Dans notre exemple, lorsque le Makex est appelé pour la première fois, la méthode Lambda Metafactory génère une instance d'un X et a lié la méthode d'exécution dynamique à la méthode Lambda 0 $. En mémoire, donc l'instance de votre deuxième appel est la même que la première fois.
L'avez-vous réparé? Y a-t-il une solution?
Il n'y a pas de réparation ou de solution directe à ce problème. Bien que le programme Java 8 d'Oracle defautedS-xdlambdatomethod, car ce paramètre ne fait pas partie de la spécification JVM, la mise en œuvre de différents fournisseurs et JVM est différente. Pour une expression Lambda, la seule chose à laquelle vous pouvez vous attendre est d'implémenter votre méthode d'interface dans la classe.
Autres méthodes
Jusqu'à présent, bien que notre imitation de Mixin ne puisse pas être compatible avec Java 8, il est toujours possible d'ajouter plusieurs services grâce à un héritage multiple et à une nomination. Cette méthode est un modèle de champ virtuel (mode champ virtuel).
Jetez donc un œil à notre commutable.
interface switchable {boolean isactive ();
Nous avons besoin d'une interface commutable et fournissons une méthode d'abstraction supplémentaire pour revenir à l'implémentation commutable. La méthode intégrée contient la définition par défaut.
Interface publique SwitchableView étend Switchable {switchable getSwitchable (); Boolean isActive () par défaut {return getSwitchable ().
Ensuite, nous créons une implémentation commutable complète:
Classe publique switchablemplt implémente Switchable {private boolean active; @Override public boolean isactive () {return active;} @Override c void setActive (boolean active) {this.active = active;}}
Ceci est un exemple de notre mode de champ virtuel:
Public Class Device {} public class Devicea étend le périphérique SwitchableView {private switchable switchableIMPl (); erride public switchable getSwitchable () {return switchable;} public class deviceB étend le périphérique switchableView {PRIDECHAB LE STOCKABLE = new switchableImpl (); Switchable getSwitchable () {return switchable;}}
en conclusion
Dans cet article, nous utilisons deux méthodes pour ajouter plusieurs services via la méthode d'extension virtuelle de Java 8. La première méthode utilise une carte pour stocker l'état d'instance. Une autre méthode consiste à utiliser un mode champ virtuel pour renvoyer l'exemple d'implémentation final via un Getter abstrait. La deuxième méthode est plus indépendante et plus sûre.
La méthode d'extension virtuelle est la nouvelle fonctionnalité de Java.