Java ne meurt pas — elle renaît
\nChaque année, quelqu'un écrit « Java est morte ». Et chaque année, Java prouve le contraire. En 2025, le langage qui a déjà presque 30 ans reçoit plusieurs mises à jour fondamentales. Si vous codez en Java, mais que vous avez regardé le changelog pour la dernière fois il y a un an — vous avez déjà du retard. Voyons concrètement ce qui va changer et comment ces changements impacteront votre code.
\nJe ne vais pas vous submerger de spécifications arides. À la place, des exemples concrets que vous pourrez exécuter dès aujourd'hui (enfin, presque). C'est parti.
\n\nThreads virtuels (Project Loom) — la fin de l'ère des blocages
\nC'est sans doute le changement le plus marquant. Les threads virtuels (virtual threads) sont des threads légers qui permettent d'écrire du code asynchrone dans un style synchrone. En 2025, ils deviennent enfin stables et recommandés pour la production.
\nAvant, vous écriviez quelque chose comme :
\nExecutorService executor = Executors.newFixedThreadPool(10);\nexecutor.submit(() -> {\n // appel bloquant\n String result = restTemplate.getForObject(url, String.class);\n return result;\n});\nLe problème, c'est que chaque thread est un objet lourd. 10 threads — ok, 10 000 — déjà des problèmes. Avec les threads virtuels, vous pouvez lancer des millions de threads sans vous soucier de la mémoire :
\ntry (var executor = Executors.newVirtualThreadPerTaskExecutor()) {\n for (int i = 0; i < 100_000; i++) {\n executor.submit(() -> {\n // maintenant c'est léger\n String result = restTemplate.getForObject(url, String.class);\n return result;\n });\n }\n}\nLa différence clé : les threads virtuels ne sont pas liés aux threads du système d'exploitation. Lorsqu'un thread se bloque (par exemple sur une opération d'E/S), la JVM bascule simplement sur un autre thread virtuel. Aucun surcoût.
\nQu'est-ce que cela signifie pour vous ? Oubliez les frameworks asynchrones complexes comme CompletableFuture et les bibliothèques réactives. En 2025, le code synchrone standard sur threads virtuels sera à la fois plus rapide et plus simple.
\n\nComment migrer
\nRemplacez newFixedThreadPool par newVirtualThreadPerTaskExecutor. Si vous utilisez Spring Boot — mettez à jour vers la version 3.2+, elle prend déjà en charge. Assurez-vous simplement que vos bibliothèques n'utilisent pas synchronized dans les sections critiques — c'est le seul point où les threads virtuels peuvent « coincer ».
Pattern Matching et Switch — le code devient plus court
\nEn 2025, le pattern matching a atteint switch et instanceof. Désormais, au lieu d'une multitude de if-else imbriqués, on peut écrire de manière concise et lisible.
Avant (ancien style) :
\nif (obj instanceof String) {\n String s = (String) obj;\n System.out.println(s.length());\n} else if (obj instanceof Integer) {\n Integer i = (Integer) obj;\n System.out.println(i * 2);\n}\nMaintenant (Java 21+) :
\nswitch (obj) {\n case String s -> System.out.println(s.length());\n case Integer i -> System.out.println(i * 2);\n case null -> System.out.println("null");\n default -> System.out.println("inconnu");\n}\nNotez le case null — c'est une amélioration distincte. Avant, switch levait une NullPointerException lors de la transmission de null. Maintenant, on peut le traiter explicitement.
Une autre fonctionnalité intéressante — les record patterns. Si vous avez un record :
\nrecord Point(int x, int y) {}\nAlors vous pouvez écrire :
\nif (obj instanceof Point(int x, int y)) {\n System.out.println("x=" + x + ", y=" + y);\n}\nSans conversion de type superflue. En 2025, cela deviendra courant — utilisez-le pour rendre le code plus propre.
\n\nRamasse-miettes : ZGC et Generational GC
\nEn 2025, le ramasse-miettes est devenu encore plus rapide. Le ZGC (Z Garbage Collector) est désormais activé par défaut pour la plupart des applications. Son