Diverses mises à jour du langage
Dans cette annexe, nous discutons de trois autres mises à jour du langage dans Java 8: les annotations répétées, les annotations de type et l’inférence généralisée de type cible. L’annexe B traite des mises à jour de bibliothèques dans Java 8. Nous ne parlons pas des mises à jour de JDK 8 telles que Nashorn et Compact Profiles car il s’agit de nouvelles fonctionnalités JVM. Ce tutoriel se concentre sur les mises à jour de la bibliothèque et du langage. Nous vous invitons à lire les liens suivants si vous êtes intéressé par Nashorn et les profils Compacts: http://openjdk.java.net/projects/nashorn/ et http://openjdk.java.net/jeps/161.
A.1. Annotations
Le mécanisme d’annotation dans Java 8 a été amélioré de deux manières:
- Vous pouvez répéter les annotations.
- Vous pouvez annoter tout type d’utilisation.
Avant d’expliquer ces mises à jour, il est utile de rafraîchir rapidement ce que vous pouviez faire avec les annotations avant Java 8.
Les annotations en Java sont un mécanisme qui vous permet de décorer des éléments de programme avec des informations supplémentaires (notez qu’avant Java 8, seules les déclarations pouvaient être annotées). En d’autres termes, c’est une forme de métadonnées syntaxiques. Par exemple, les annotations sont populaires avec le framework JUnit. Dans le code suivant, la méthode setUp est annotée avec l’annotation @Before et la méthode testAlgorithm est annotée avec @Test:
Les annotations conviennent à plusieurs cas d’utilisation:
- Dans le contexte de JUnit, les annotations peuvent différencier les méthodes qui doivent être exécutées en tant que test unitaire et les méthodes utilisées pour le travail d’installation.
- Les annotations peuvent être utilisées pour la documentation. Par exemple, l’annotation @Deprecated est utilisée pour indiquer qu’une méthode ne doit plus être utilisée.
- Le compilateur Java peut également traiter des annotations afin de détecter des erreurs, supprimer des avertissements ou générer du code.
- Les annotations sont populaires dans Java EE, où elles sont utilisées pour configurer des applications d’entreprise.
A.1.1. Annotations répétées
Les versions précédentes de Java interdisent de spécifier plus d’une annotation d’un type d’annotation donné dans une déclaration. Pour cette raison, le code suivant est invalide:
Les programmeurs Java EE utilisent souvent un idiome pour contourner cette restriction. Vous déclarez une nouvelle annotation, qui contient un tableau de l’annotation que vous souhaitez répéter. Cela ressemble à ceci:
L’annotation imbriquée dans la classe Book est plutôt moche. C’est pourquoi Java 8 supprime essentiellement cette restriction, qui complexifie un peu les choses. Vous êtes maintenant autorisé à spécifier plusieurs annotations du même type d’annotation sur une déclaration, à condition qu’elles stipulent que l’annotation est répétable. Ce n’est pas le comportement par défaut. vous devez demander explicitement qu’une annotation soit répétable.
Faire une annotation répétable
Si une annotation a été conçue pour être répétable, vous pouvez simplement l’utiliser. Mais si vous fournissez des annotations pour vos utilisateurs, la configuration est requise pour spécifier qu’une annotation peut être répétée. Il y a deux étapes:
- Marquez l’annotation comme @Repeatable.
- Fournissez une annotation de conteneur.
Voici comment vous pouvez répéter l’annotation @Author:
Par conséquent, la classe Book peut être annotée avec plusieurs annotations @Author:
Au moment de la compilation, Book est considéré comme étant annoté par @Authors ({@Author (nom = « Raoul »), @Author (nom = « Mario »), @Author (nom = « Alan »)}, ainsi vous pouvez voir ce nouveau mécanisme comme sucre syntaxique autour de l’idiome précédent utilisé par les programmeurs Java. Les annotations sont toujours enveloppées dans un conteneur pour garantir la compatibilité comportementale avec les méthodes de réflexion héritées. La méthode getAnnotation (Class <T> annotationClass) dans l’API Java renvoie l’annotation de type T pour un élément annoté. Quelle annotation cette méthode devrait renvoyer s’il y a plusieurs annotations de type T?
Sans entrer dans les détails, la classe Class prend en charge une nouvelle méthode getAnnotationsByType qui facilite le travail avec des annotations répétables. Par exemple, vous pouvez l’utiliser comme suit pour imprimer toutes les annotations Author de la classe Book:
Pour que cela fonctionne, l’annotation répétable et son conteneur doivent avoir une stratégie de rétention RUNTIME. Plus d’informations sur la compatibilité avec les méthodes de réflexion existantes peuvent être trouvées ici: http://cr.openjdk.java.net/~abuckley/8misc.pdf.
A.1.2. Les annotations de types
Depuis Java 8, les annotations peuvent également être appliquées à tout type utilisé. Cela inclut l’opérateur new, les types castés, les vérifications d’instanceof, les arguments de type générique et les clauses implements et throws. Ici nous indiquons que le nom de variable de type String ne peut pas être nul en utilisant une annotation @NonNull:
De même, vous pouvez annoter le type des éléments d’une liste:
Pourquoi est-ce intéressant? Les annotations sur les types peuvent être utiles pour effectuer une analyse de programme. Dans ces deux exemples, un outil pourrait s’assurer que getName ne retourne pas null et que les éléments de la liste des voitures sont toujours non-null. Cela peut aider à réduire les erreurs inattendues dans votre code.
Java 8 ne fournit pas d’annotations officielles ni d’outil permettant de les utiliser directement. Il fournit uniquement la possibilité d’utiliser des annotations sur les types. Heureusement, un outil appelé le framework Checker existe, qui définit plusieurs annotations de type et vous permet d’améliorer la vérification de type en les utilisant. Si vous êtes curieux, nous vous invitons à consulter son tutoriel: http://www.checker-framework.org. Vous trouverez plus d’informations sur l’emplacement des annotations dans votre code ici: http://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.7.4.
A.2. Inférence de type cible généralisée
Java 8 améliore l’inférence des arguments génériques. Vous connaissez déjà l’inférence de type en utilisant des informations de contexte antérieures à Java 8. Par exemple, la méthode liste vide en Java est définie comme suit:
La méthode emptyList est paramétrée avec le paramètre de type T. Vous pouvez l’appeler comme suit pour fournir un type explicite au paramètre type:
Mais Java est capable d’inférer l’argument générique. Ce qui suit est équivalent:
Avant Java 8, ce mécanisme d’inférence basé sur le contexte (c’est-à-dire le typage de la cible) était limité. Par exemple, ce qui suit n’était pas possible:
Vous obtiendrez l’erreur suivante: cleanCars (java.util.List<Car>)cannot be applied to (java.util.List<java.lang.Object>)
Pour le réparer, vous devrez fournir un argument de type explicite comme celui que nous avons montré précédemment.
Dans Java 8, le type cible inclut des arguments à une méthode, vous n’avez donc pas besoin de fournir un argument générique explicite:
Dans ce code, c’est exactement cette amélioration qui vous permet d’écrire Collectors.toList () à la place de Collectors. <Car> toList ().