Open

OpenJDK 21 (prochaine LTS Java) : quoi de neuf ?

Valentin Courtois, Tech Lead @DeliaTechnologies
Valentin Courtois, Tech Lead @DeliaTechnologies
July 13, 2023
7 min

Historique et fonctionnement

Depuis fin 2017 et la sortie du JDK 9, Oracle sort une nouvelle version de leur tant utilisée bibliothèque tous les 6 mois. Pour se permettre de pousser des évolutions plus ambitieuses sans rechercher en permanence la stabilité à toute épreuve, les équipes ont décidé que seules certaines de ces versions, au maximum une tous les deux ans, serait estampillée long-term support (LTS). C’est également en 2017 qu’Oracle a rendu le support sur son JDK payant, et que la version open-source du JDK « OpenJDK » est réellement montée sur le devant de la scène. Pour la suite de cet article, nous nous intéresserons spécifiquement aux évolutions côté OpenJDK.

Les plus récentes LTS du JDK sont les versions 8 (début 2014), 11 (fin 2018) et 17 (fin 2021). La prochaine cible est donc le JDK 21, prévu au 19 septembre 2023. Mais qu’ajoute-t-il donc par rapport à ses prédécesseurs ?

Du tout nouveau !

Les relectures par OpenJDK pour la plupart des fonctionnalités qui avaient été proposées se sont terminées le 16 mai 2023.

Sequenced Collections

L’une d’entre elles est la JEP 431, sur les SequencedCollection. Vous en avez marre de devoir itérer toute votre liste pour aller chercher le dernier élément ? Cette fonctionnalité est pour vous ! Les équipes se sont rendues compte que parfois elles avaient besoin d’une structure ordonnée et parfois non, mais que c’était le même objet qui répondait aux deux attentes. De plus, par généricité avec des types spécifiquement non séquencés (comme HashSet), il est possible de “perdre” l’information de séquençage. Pour remédier à cela, l’interface SequencedCollection<E> extends Collection<E> va être ajoutée à la librairie. Elle s’inspire notamment de ce qui est présent dans Deque, en permettant l’usage générique des fonctions addFirst(), addLast(), getFirst(), getLast(), removeFirst() et removeLast(). Elle contiendra également une fonction reversed() qui évitera de passer par une Stream systématiquement. Attention cependant, cette fonction reversed() est équivalente à NavigableSet::descendingSet, et n’offre donc qu’une vueinversée de l’objet courant ; toute modification appliquée sur la vue inversée est également appliquée sur l’objet. Les nouvelles interfaces SequencedSet et SequencedMap seront également intégrées à la librairie pour homogénéiser tous nos types de collections. Ci-dessous, en vert les nouvelles interfaces.

Record Patterns

C’est une sortie de preview pour les record patterns (JEP 440) ! Depuis le JDK 16, les Record permettent de stocker des données non mutables, sans accesseurs et avec un constructeur canonique par défaut (permettant la valorisation définitive des champs de l’instance ainsi créée). Il est cependant possible de surcharger ce constructeur canonique pour ajouter des règles spécifiques, comme sur cet exemple :

Le pattern-matching via instanceof a déjà bien amélioré la qualité de vie des développeurs en permettant de ne plus avoir à cast les objets en ce que nous venions de vérifier qu’ils sont :

Le compilateur comprend maintenant que la clause if permet qu’à cet endroit l’objet ne peut être que du type contrôlé. Eh bien ce sera le cas également pour les classes avec le mot clé record et leurs attributs ! Cela permettra de faire du nested pattern-matching, comme dans cet exemple où l’on déconstruit un Rectangle en profondeur via instanceof :

Le pattern-matching pour les switch, enfin en cible

Après quatre séquences de preview, l’entrée définitive du pattern-matching pour les switch en librairie est bel et bien en cible (JEP 441) ! Mais … de quoi parle-t-on ?

La plupart des langages modernes, qu’ils utilisent la JVM ou non, possèdent déjà des manières bien plus élégantes que Java de faire du pattern-matching multiple. Scala pour ne pas le citer utilise par exemple des sealed trait et case class, permettant déjà de faire un simple switch pour tester le type d’un objet. Java se mettra donc à la page, permettant enfin cette syntaxe :

Il faut noter que ces nouveaux case accepteront également les gardes (existant également déjà en Scala …) avec la clause when, plutôt que de devoir mettre des structures conditionnelles en retour de cas :

De plus, cet ajoute profitera également de l’ajout des Record Patterns, pour pouvoir intégrer à des switch du nested record pattern-matching … De quoi réellement réduire la complexité cyclomatique de nombreuses de vos fonctions !

Virtual Threads et optimisation

Les threads virtuels (JEP 444), entrés au JDK 19 en preview, en seront sortis pour le JDK 21. Ils permettront de ne pas monopoliser un thread du système d’exploitation, à l’instar des Thread historiques du JDK. Ils seront accompagnés d’un scheduler spécifique, et serviront pour instancier des actions unitaires pour une meilleure parallélisation des actions - et donc une exécution globale de votre programme plus rapide ! Pour couronner le tout, deux autres JEP d’optimisation sont actuellement en étude, sur les garbage collectors générationnels (JEP 404: Generational Shenandoah, JEP 439: Generational ZGC).

Des fonctionnalités en preview

Plusieurs preview sont en étude pour entrer dans le JDK 21 ! Si vous voulez les tester une fois qu’elles seront intégrées, il vous suffit d’ajouter --enable-preview à la compilation du programme.

Classes, variables … non nommées ?

Vous ne rêvez pas ! La JEP 445 permet d’abstraire la déclaration de classes autour d’une fonction ! La spécification du langage Java (JLS) n’explicitant nulle part la nécessité de telles fioritures, si le cadre s’y prête il n’y a pas de raison de les rendre nécessaire. Ainsi, secondant l’idée de modernisation de Java suite à l’implémentation d’un source code launcher, il sera enfin possible de s’épargner le sempiternel public static void main(String[] args) et de simplement écrire un Hello, World! de cette manière :

De quoi ravir les code-golfers parmi vous ! Et simplifier pour beaucoup l’apprentissage du langage pour les étudiant·es, sans avoir à s’attarder sur des faiblesses de compilateur. Tous les petits programmes pourront s’exécuter au sein d’une top-level class non nommée.

Quid des variables ? Reprenons un exemple précédent.

Ici, nous avons défini la variable r pour la décomposer et récupérer la couleur c dans l’un des ColoredPoint du Rectangle r. Cependant, cela nous a amené à définir malgré nous les variables Point p et ColoredPoint lr, dont nous ne comptions pas nous servir. Cela n’est dû qu’à une règle du compilateur Java, qui souhaite que tout soit nommé. Ce n’est pourtant pas nécessaire, de nombreux langages (notamment Scala …) utilisent _ par exemple pour parler de cas par défaut ou de variable inutile. Java se met encore une fois à la page, avec la JEP 443 !

En Java 1.0, le caractère _ était autorisé en tant que nom de variable, depuis 2014 une alerte est déclenchée (mais pas d’erreur), depuis Java 9 il soulève une erreur de compilation, et maintenant il est totalement réservé aux variables joker. Mieux vaut tard que jamais !

String Templates

Finie la concaténation de chaînes avec des +, finie la verbosité des StringBuilder, place à la lisibilité et la maintenabilité avec la JEP 430 !

La forme template \{<code>} permet de valoriser une expression au sein d’une String, grâce au champ STR importé automatiquement dans tous vos fichiers source. Il existe également un champ FMT permettant un formatage plus poussé, notamment pour afficher des données plus complexes :

Conclusion

Vous pouvez dès à présent vous familiariser avec ces fonctionnalités, et les intégrer à votre manière de développer. Il existe même des builds en accès anticipé pour tester dès maintenant avec le compilateur. Il faudra penser à mettre à jour les linters, les règles Sonar, les librairies connexes … de sorte à intégrer à vos projets pro comme perso ces nouvelles fonctionnalités !

NB : les exemples dans cet article sont en grande partie inspirés des pages du site d’OpenJDK traitant des JEP (JDK Enhancement Proposals, ou « propositions d’amélioration du JDK ») correspondantes. Pour plus de détails, n’hésitez pas à consulter les pages en question, qui sont en hyperliens dans l’article.

D'autres articles pour vous

Tous nos articles →
photo camille

Envie de rejoindre l'aventure ?

Réservez un moment avec notre équipe RH en quelques clics, pour voir ensemble le meilleur moyen de nous rejoindre. Vous avez des questions sur Delia Technologies ? C'est le moment de les poser !

Rencontrer notre équipe