Maison Java javaDidacticiel Fonctionnalités Java : un aperçu détaillé des changements les plus importants dans la nouvelle version LTS

Fonctionnalités Java : un aperçu détaillé des changements les plus importants dans la nouvelle version LTS

Jul 29, 2024 pm 08:39 PM

Une autre version Java LTS est déjà là, apportant des changements et des améliorations passionnants. Analysons les fonctionnalités les plus importantes de Java 21, voyons comment elles fonctionnent dans la pratique et essayons de prédire leur importance pour l'avenir de cette technologie.

Depuis que la plateforme Java a adopté un cycle de publication de six mois, nous avons dépassé les questions récurrentes telles que « Java mourra-t-il cette année ? » ou "Vaut-il la peine de migrer vers la nouvelle version ?". Malgré 28 ans depuis sa première version, Java continue de prospérer et reste un choix populaire comme langage de programmation principal pour de nombreux nouveaux projets.

Java 17 a constitué une étape importante, mais Java 21 a désormais pris la place de 17 en tant que prochaine version de support à long terme (LTS). Il est essentiel pour les développeurs Java de rester informés des changements et des nouvelles fonctionnalités apportées par cette version. Inspiré par mon collègue Darek, qui a détaillé les fonctionnalités de Java 17 dans son article, j'ai décidé de discuter du JDK 21 de la même manière.

JDK 21 comprend un total de 15 JEP (JDK Enhancement Proposals). Vous pouvez consulter la liste complète sur le site officiel Java. Dans cet article, je mettrai en évidence plusieurs JEP Java 21 qui, à mon avis, sont particulièrement remarquables. A savoir :

  1. Modèles de chaînes
  2. Collections séquencées
  3. Correspondance de modèles pour les modèles de commutation et d'enregistrement
  4. Fils virtuels

Sans plus attendre, examinons le code et explorons ces mises à jour.

Modèles de chaînes (aperçu)

La fonctionnalité Spring Templates est toujours en mode aperçu. Pour l'utiliser, vous devez ajouter l'indicateur –enable-preview aux arguments de votre compilateur. Cependant, j’ai décidé de le mentionner malgré son statut d’aperçu. Pourquoi? Parce que je suis très irrité à chaque fois que je dois écrire un message de journal ou une instruction SQL contenant de nombreux arguments ou déchiffrer quel espace réservé sera remplacé par un argument donné. Et Spring Templates promet de m'aider (et vous) avec cela.

Comme le dit la documentation JEP, le but des modèles Spring est de « simplifier l'écriture de programmes Java en facilitant l'expression de chaînes qui incluent des valeurs calculées au moment de l'exécution ».

Vérifions si c'est vraiment plus simple.

L'ancienne méthode serait d'utiliser la méthode formatted() sur un objet String :

var msg = "Log message param1: %s, pram2: %s".formatted(p1, p2);
Copier après la connexion

Maintenant, avec StringTemplate.Processor (STR), cela ressemble à ceci :

var interpolated = STR."Log message param1: \{p1}, param2: \{p2}";
Copier après la connexion

Avec un texte court comme celui ci-dessus, le profit n'est peut-être pas si visible – mais croyez-moi, lorsqu'il s'agit de gros blocs de texte (jsons, instructions sql), les paramètres nommés vous aideront beaucoup.

Collections séquencées

Java 21 a introduit une nouvelle hiérarchie de collections Java. Regardez le schéma ci-dessous et comparez-le à ce que vous avez probablement appris lors de vos cours de programmation. Vous remarquerez que trois nouvelles structures ont été ajoutées (surlignées par la couleur verte).

Java features: A detailed look at the most important changes in the new LTS release
Source : JEP 431

Les collections séquencées introduisent une nouvelle API Java intégrée, améliorant les opérations sur les ensembles de données ordonnés. Cette API permet non seulement un accès pratique aux premier et dernier éléments d'une collection, mais permet également un parcours efficace, une insertion à des positions spécifiques et une récupération de sous-séquences. Ces améliorations rendent les opérations qui dépendent de l'ordre des éléments plus simples et plus intuitives, améliorant à la fois les performances et la lisibilité du code lorsque vous travaillez avec des listes et des structures de données similaires.

Voici la liste complète de l'interface SequencedCollection :

public interface SequencedCollection<E> extends Collection<E> {
   SequencedCollection<E> reversed();
   default void addFirst(E e) {
       throw new UnsupportedOperationException();
   }
   default void addLast(E e) {
       throw new UnsupportedOperationException();
   }
   default E getFirst() {
       return this.iterator().next();
   }
   default E getLast() {
       return this.reversed().iterator().next();
   }
   default E removeFirst() {
       var it = this.iterator();
       E e = it.next();
       it.remove();
       return e;
   }
   default E removeLast() {
       var it = this.reversed().iterator();
       E e = it.next();
       it.remove();
       return e;
   }
}
Copier après la connexion

Alors, maintenant, au lieu de :

var first = myList.stream().findFirst().get();
var anotherFirst = myList.get(0);
var last = myList.get(myList.size() - 1);
Copier après la connexion

On peut juste écrire :

var first = sequencedCollection.getFirst();
var last = sequencedCollection.getLast();
var reversed = sequencedCollection.reversed();
Copier après la connexion

Un petit changement, mais à mon humble avis, c'est une fonctionnalité tellement pratique et utilisable.

Correspondance de modèles et modèles d'enregistrement

En raison de la similitude de la correspondance de modèles pour les switch et les modèles d'enregistrement, je vais les décrire ensemble. Les modèles d'enregistrement sont une nouvelle fonctionnalité – ils ont été introduits dans Java 19 (en avant-première). D'un autre côté, Pattern Matching pour switch est en quelque sorte une continuation de l'instance étendue d'expression. Il apporte une nouvelle syntaxe possible pour les instructions switch qui vous permet d'exprimer plus facilement des requêtes complexes orientées données.

Oublions les bases de la POO pour le bien de cet exemple et déconstruisons l'objet employé manuellement (employé est une classe POJO).

Avant Java 21, cela ressemblait à ceci :

if (employee instanceof Manager e) {
   System.out.printf("I’m dealing with manager of %s department%n", e.department);
} else if (employee instanceof Engineer e) {
   System.out.printf("I’m dealing with %s engineer.%n", e.speciality);
} else {
   throw new IllegalStateException("Unexpected value: " + employee);
}
Copier après la connexion

Et si nous pouvions nous débarrasser de la vilaine instanceof ? Eh bien, maintenant nous pouvons, grâce à la puissance du Pattern Matching de Java 21 :

switch (employee) {
   case Manager m -> printf("Manager of %s department%n", m.department);
   case Engineer e -> printf("I%s engineer.%n", e.speciality);
   default -> throw new IllegalStateException("Unexpected value: " + employee);
}
Copier après la connexion

While talking about the switch statement, we can also discuss the Record Patterns feature. When dealing with a Java Record, it allows us to do much more than with a standard Java class:

switch (shape) { // shape is a record
   case Rectangle(int a, int b) -> System.out.printf("Area of rectangle [%d, %d] is: %d.%n", a, b, shape.calculateArea());
   case Square(int a) -> System.out.printf("Area of square [%d] is: %d.%n", a, shape.calculateArea());
   default -> throw new IllegalStateException("Unexpected value: " + shape);
}
Copier après la connexion

As the code shows, with that syntax, record fields are easily accessible. Moreover, we can put some additional logic to our case statements:

switch (shape) {
   case Rectangle(int a, int b) when a < 0 || b < 0 -> System.out.printf("Incorrect values for rectangle [%d, %d].%n", a, b);
   case Square(int a) when a < 0 -> System.out.printf("Incorrect values for square [%d].%n", a);
   default -> System.out.println("Created shape is correct.%n");
}
Copier après la connexion

We can use similar syntax for the if statements. Also, in the example below, we can see that Record Patterns also work for nested records:

if (r instanceof Rectangle(ColoredPoint(Point p, Color c),
                          ColoredPoint lr)) {
   //sth
}
Copier après la connexion

Virtual Threads

The Virtual Threads feature is probably the hottest one among all Java 21 – or at least one the Java developers have waited the most for. As JEP documentation (linked in the previous sentence) says, one of the goals of the virtual threads was to “enable server applications written in the simple thread-per-request style to scale with near-optimal hardware utilization”. However, does this mean we should migrate our entire code that uses java.lang.Thread?

First, let’s examine the problem with the approach that existed before Java 21 (in fact, pretty much since Java’s first release). We can approximate that one java.lang.Thread consumes (depending on OS and configuration) about 2 to 8 MB of memory. However, the important thing here is that one Java Thread is mapped 1:1 to a kernel thread. For simple web apps which use a “one thread per request” approach, we can easily calculate that either our machine will be “killed” when traffic increases (it won’t be able to handle the load) or we’ll be forced to purchase a device with more RAM, and our AWS bills will increase as a result.

Of course, virtual threads are not the only way to handle this problem. We have asynchronous programming (frameworks like WebFlux or native Java API like CompletableFuture). However, for some reason – maybe because of the “unfriendly API” or high entry threshold – these solutions aren’t that popular.

Virtual Threads aren’t overseen or scheduled by the operating system. Rather, their scheduling is handled by the JVM. While real tasks must be executed in a platform thread, the JVM employs so-called carrier threads — essentially platform threads — to “carry” any virtual thread when it is due for execution. Virtual Threads are designed to be lightweight and use much less memory than standard platform threads.

The diagram below shows how Virtual Threads are connected to platform and OS threads:

Java features: A detailed look at the most important changes in the new LTS release

So, to see how Virtual Threads are used by Platform Threads, let’s run code that starts (1 + number of CPUs the machine has, in my case 8 cores) virtual threads.

var numberOfCores = 8; //
final ThreadFactory factory = Thread.ofVirtual().name("vt-", 0).factory();
try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
   IntStream.range(0, numberOfCores + 1)
           .forEach(i -> executor.submit(() -> {
               var thread = Thread.currentThread();
               System.out.println(STR."[\{thread}]  VT number: \{i}");
               try {
                   sleep(Duration.ofSeconds(1L));
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }));
}
Copier après la connexion

Output looks like this:

[VirtualThread[#29,vt-6]/runnable@ForkJoinPool-1-worker-7]  VT number: 6
[VirtualThread[#26,vt-4]/runnable@ForkJoinPool-1-worker-5]  VT number: 4
[VirtualThread[#30,vt-7]/runnable@ForkJoinPool-1-worker-8]  VT number: 7
[VirtualThread[#24,vt-2]/runnable@ForkJoinPool-1-worker-3]  VT number: 2
[VirtualThread[#23,vt-1]/runnable@ForkJoinPool-1-worker-2]  VT number: 1
[VirtualThread[#27,vt-5]/runnable@ForkJoinPool-1-worker-6]  VT number: 5
[VirtualThread[#31,vt-8]/runnable@ForkJoinPool-1-worker-6]  VT number: 8
[VirtualThread[#25,vt-3]/runnable@ForkJoinPool-1-worker-4]  VT number: 3
[VirtualThread[#21,vt-0]/runnable@ForkJoinPool-1-worker-1]  VT number: 0
Copier après la connexion

So, ForkJonPool-1-worker-X Platform Threads are our carrier threads that manage our virtual threads. We observe that Virtual Threads number 5 and 8 are using the same carrier thread number 6.

The last thing about Virtual Threads I want to show you is how they can help you with the blocking I/O operations.

Whenever a Virtual Thread encounters a blocking operation, such as I/O tasks, the JVM efficiently detaches it from the underlying physical thread (the carrier thread). This detachment is critical because it frees up the carrier thread to run other Virtual Threads instead of being idle, waiting for the blocking operation to complete. As a result, a single carrier thread can multiplex many Virtual Threads, which could number in the thousands or even millions, depending on the available memory and the nature of tasks performed.

Let’s try to simulate this behavior. To do this, we will force our code to use only one CPU core, with only 2 virtual threads – for better clarity.

System.setProperty("jdk.virtualThreadScheduler.parallelism", "1");
System.setProperty("jdk.virtualThreadScheduler.maxPoolSize", "1");
System.setProperty("jdk.virtualThreadScheduler.minRunnable", "1");
Copier après la connexion

Thread 1:

Thread v1 = Thread.ofVirtual().name("long-running-thread").start(
       () -> {
           var thread = Thread.currentThread();
           while (true) {
               try {
                   Thread.sleep(250L);
                   System.out.println(STR."[\{thread}] - Handling http request ....");
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
       }
);
Copier après la connexion

Thread 2:

Thread v2 = Thread.ofVirtual().name("entertainment-thread").start(
       () -> {
           try {
               Thread.sleep(1000L);
           } catch (InterruptedException e) {
               throw new RuntimeException(e);
           }
           var thread = Thread.currentThread();
           System.out.println(STR."[\{thread}] - Executing when 'http-thread' hit 'sleep' function");
       }
);
Copier après la connexion

Execution:

v1.join();
v2.join();
Copier après la connexion

Result:

[VirtualThread[#21,long-running-thread]/runnable@ForkJoinPool-1-worker-1] - Handling http request ....
[VirtualThread[#21,long-running-thread]/runnable@ForkJoinPool-1-worker-1] - Handling http request ....
[VirtualThread[#21,long-running-thread]/runnable@ForkJoinPool-1-worker-1] - Handling http request ....
[VirtualThread[#23,entertainment-thread]/runnable@ForkJoinPool-1-worker-1] - Executing when 'http-thread' hit 'sleep' function
[VirtualThread[#21,long-running-thread]/runnable@ForkJoinPool-1-worker-1] - Handling http request ....
[VirtualThread[#21,long-running-thread]/runnable@ForkJoinPool-1-worker-1] - Handling http request ....
[VirtualThread[#21,long-running-thread]/runnable@ForkJoinPool-1-worker-1] - Handling http request ....
[VirtualThread[#21,long-running-thread]/runnable@ForkJoinPool-1-worker-1] - Handling http request ....
[VirtualThread[#21,long-running-thread]/runnable@ForkJoinPool-1-worker-1] - Handling http request ....
[VirtualThread[#21,long-running-thread]/runnable@ForkJoinPool-1-worker-1] - Handling http request ....
Copier après la connexion

We observe that both Virtual Threads (long-running-thread and entertainment-thread) are being carried by only one Platform Thread which is ForkJoinPool-1-worker-1.

To summarize, this model enables Java applications to achieve high levels of concurrency and scalability with much lower overhead than traditional thread models, where each thread maps directly to a single operating system thread. It’s worth noting that virtual threads are a vast topic, and what I’ve described is only a small fraction. I strongly encourage you to learn more about the scheduling, pinned threads and the internals of VirtualThreads.

Résumé : L'avenir du langage de programmation Java

Les fonctionnalités décrites ci-dessus sont celles que je considère comme les plus importantes de Java 21. La plupart d'entre elles ne sont pas aussi révolutionnaires que certaines des choses introduites dans le JDK 17, mais elles restent très utiles et agréables à utiliser. avoir des changements de QOL (Qualité de Vie).

Cependant, vous ne devriez pas non plus négliger les autres améliorations du JDK 21 – je vous encourage vivement à analyser la liste complète et à explorer plus en détail toutes les fonctionnalités. Par exemple, une chose que je considère particulièrement remarquable est l’API Vector, qui permet des calculs vectoriels sur certaines architectures de processeur prises en charge – ce qui n’était pas possible auparavant. Actuellement, il est encore au stade d’incubateur/phase expérimentale (c’est pourquoi je ne l’ai pas présenté plus en détail ici), mais il est très prometteur pour l’avenir de Java.

Dans l'ensemble, les progrès réalisés par Java dans divers domaines témoignent de l'engagement continu de l'équipe à améliorer l'efficacité et les performances des applications à forte demande.

Si Java vous intéresse, n'oubliez pas de consulter certains de nos autres articles :

  1. Fonctionnalités Java 17 : Une comparaison entre les versions 8 et 17. Qu'est-ce qui a changé au fil des années ?
  2. JVM Kubernetes : optimisation de Kubernetes pour les développeurs Java
  3. Projet Valhalla – Java sur la voie de meilleures performances
  4. Questions d'entretien Java avancées : un guide pour 2023

FAQ sur les fonctionnalités Java

Voici les réponses à quelques questions courantes concernant le JDK 21, ainsi que l'interface et les fonctionnalités natives de Java.

Qu’est-ce que Java SE ?

Java SE (Java Platform, Standard Edition) est une plateforme fondamentale pour développer et déployer des applications Java sur des postes de travail et des serveurs.

Qu'est-ce que l'API des fonctions étrangères et de la mémoire ?

Il s'agit d'une fonctionnalité d'aperçu qui permet aux programmes Java d'interagir avec des données et du code en dehors du runtime Java. L'API permet aux programmes Java d'appeler des bibliothèques natives et de traiter les données natives de manière plus sûre que dans le cas de JNI. L'API est un outil permettant d'accéder en toute sécurité à la mémoire et au code étrangers et d'invoquer efficacement des fonctions étrangères.

Comment bien écrire du code Java ?

L'un des aspects clés est la révision du code (vous pouvez utiliser les outils de révision du code de l'IA pour rendre ce processus un peu moins long).

Qu’est-ce que le chargement dynamique en Java ?

Le chargement dynamique en Java fait référence au chargement de classes ou de ressources au moment de l'exécution, plutôt que lors du démarrage initial du programme.

Qu’est-ce que la concurrence structurée ?

La concurrence structurée en Java est une approche qui organise les processus simultanés de manière contrôlée, visant à améliorer la maintenabilité, la fiabilité et l'observabilité du code multithread.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

<🎜>: Grow A Garden - Guide de mutation complet
3 Il y a quelques semaines By DDD
<🎜>: Bubble Gum Simulator Infinity - Comment obtenir et utiliser les clés royales
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Comment déverrouiller le grappin
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Système de fusion, expliqué
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel Java
1668
14
Tutoriel PHP
1273
29
Tutoriel C#
1256
24
Le logiciel de sécurité de l'entreprise entraîne-t-il l'exécution de l'application? Comment dépanner et le résoudre? Le logiciel de sécurité de l'entreprise entraîne-t-il l'exécution de l'application? Comment dépanner et le résoudre? Apr 19, 2025 pm 04:51 PM

Dépannage et solutions au logiciel de sécurité de l'entreprise qui fait que certaines applications ne fonctionnent pas correctement. De nombreuses entreprises déploieront des logiciels de sécurité afin d'assurer la sécurité des réseaux internes. ...

Comment convertir les noms en nombres pour implémenter le tri et maintenir la cohérence en groupes? Comment convertir les noms en nombres pour implémenter le tri et maintenir la cohérence en groupes? Apr 19, 2025 pm 11:30 PM

Solutions pour convertir les noms en nombres pour implémenter le tri dans de nombreux scénarios d'applications, les utilisateurs peuvent avoir besoin de trier en groupe, en particulier en un ...

Comment simplifier les problèmes de cartographie des champs dans l'amarrage du système à l'aide de mapstruct? Comment simplifier les problèmes de cartographie des champs dans l'amarrage du système à l'aide de mapstruct? Apr 19, 2025 pm 06:21 PM

Le traitement de la cartographie des champs dans l'amarrage du système rencontre souvent un problème difficile lors de l'exécution d'amarrage du système: comment cartographier efficacement les champs d'interface du système a ...

Comment Intellij Idea identifie-t-elle le numéro de port d'un projet de démarrage de printemps sans publier un journal? Comment Intellij Idea identifie-t-elle le numéro de port d'un projet de démarrage de printemps sans publier un journal? Apr 19, 2025 pm 11:45 PM

Commencez le printemps à l'aide de la version IntelliJideaultimate ...

Comment obtenir élégamment des noms de variables de classe d'entité pour créer des conditions de requête de base de données? Comment obtenir élégamment des noms de variables de classe d'entité pour créer des conditions de requête de base de données? Apr 19, 2025 pm 11:42 PM

Lorsque vous utilisez MyBatis-Plus ou d'autres cadres ORM pour les opérations de base de données, il est souvent nécessaire de construire des conditions de requête en fonction du nom d'attribut de la classe d'entité. Si vous manuellement à chaque fois ...

Comment convertir en toute sécurité les objets Java en tableaux? Comment convertir en toute sécurité les objets Java en tableaux? Apr 19, 2025 pm 11:33 PM

Conversion des objets et des tableaux Java: Discussion approfondie des risques et des méthodes correctes de la conversion de type de distribution De nombreux débutants Java rencontreront la conversion d'un objet en un tableau ...

Plateforme de commerce électronique SKU et conception de la base de données SPU: comment prendre en compte à la fois les attributs définis par l'utilisateur et les produits sans attribution? Plateforme de commerce électronique SKU et conception de la base de données SPU: comment prendre en compte à la fois les attributs définis par l'utilisateur et les produits sans attribution? Apr 19, 2025 pm 11:27 PM

Explication détaillée de la conception des tables SKU et SPU sur les plates-formes de commerce électronique Cet article discutera des problèmes de conception de la base de données de SKU et SPU dans les plateformes de commerce électronique, en particulier comment gérer les ventes définies par l'utilisateur ...

Comment utiliser la solution Redis Cache pour réaliser efficacement les exigences de la liste de classement des produits? Comment utiliser la solution Redis Cache pour réaliser efficacement les exigences de la liste de classement des produits? Apr 19, 2025 pm 11:36 PM

Comment la solution de mise en cache Redis réalise-t-elle les exigences de la liste de classement des produits? Pendant le processus de développement, nous devons souvent faire face aux exigences des classements, comme l'affichage d'un ...

See all articles