Java est l'un des langages de programmation les plus utilisés au monde. Sorti en 1996, il continue d'évoluer pour répondre aux besoins croissants des développeurs modernes et rester compétitif. Aujourd'hui, JavaLangage de développement très populaire ! fait tourner des milliers d'applications dans les organisations : il n'est pas prêt de disparaître ! On vous propose un petit tour d'horizon de ses nouveautés :)
Les threads virtuels sont une avancée majeure pour le modèle de concurrence en Java. Ils permettent de créer des milliers de threads légers, gérés par la machine virtuelle Java (JVM), contrairement aux threads traditionnels qui dépendent des threads du système d'exploitation. Cette approche améliore la scalabilité des applications en réduisant la surcharge de gestion des threads.
Pour démarrer un thread virtuel, il suffit d'utiliser la méthode startVirtualThread
de la classe Thread
:
Thread.startVirtualThread(/*Runnable*/);
La concurrence structurée est une technique qui simplifie la gestion des tâches concurrentes en organisant l'exécution des tâches dans une structure hiérarchique. Elle garantit que toutes les tâches lancées au sein d'une structure donnée sont terminées avant que le contrôle ne soit rendu à l'appelant. Cela facilite la gestion des ressources et améliore la fiabilité du code concurrent.
Les threads locaux permettent de stocker des données spécifiques à un thread. Cette fonctionnalité est utile pour maintenir des états isolés entre différents threads, améliorant ainsi la sécurité et la modularité du code concurrent.
public class MonRunnable implements Runnable {
private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();
@Override
public void run() {
System.out.printf("Thread %s -> threadLocal: %s%n", Thread.currentThread().getName(), threadLocal);
threadLocal.set("valeur pour %s".formatted(Thread.currentThread().getName()));
try {
Thread.sleep(1_000);
System.out.printf("Thread %s -> threadLocal: %s%n", Thread.currentThread().getName(), threadLocal.get());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
Thread thread1 = new Thread(new MonRunnable());
Thread thread2 = new Thread(new MonRunnable());
thread1.start();
thread2.start();
}
}
Thread Thread-0 -> threadLocal: java.lang.ThreadLocal@7441c9f7
Thread Thread-1 -> threadLocal: java.lang.ThreadLocal@7441c9f7
Thread Thread-1 -> threadLocal: valeur pour Thread-1
Thread Thread-0 -> threadLocal: valeur pour Thread-0
Les motifs d'enregistrement (records pattern) offrent une manière concise et claire de définir des classes immuables qui sont principalement des conteneurs pour les données. Les records réduisent le code boilerplate en générant automatiquement des méthodes telles que equals()
, hashCode()
et toString()
, basées sur les composants de données définis.
Les variables et instances anonymes permettent de déclarer des variables sans nom explicite, simplifiant ainsi le code pour les cas où le nom de la variable n'ajoute pas de clarté supplémentaire. Cela peut être particulièrement utile dans les expressions lambda et les flux de traitement de données.
public class Main {
public static void main(String[] args) {
String _ = "Ceci est une variable anonyme";
}
}
Les constructeurs flexibles offrent une nouvelle syntaxe pour définir des constructeurs, permettant de créer des objets avec une plus grande flexibilité et clarté. Cette fonctionnalité simplifie la création d'objets complexes et améliore la lisibilité du code.
Les collecteurs de flux sont des outils puissants pour traiter les collections de données de manière déclarative. Ils permettent de collecter, filtrer et transformer des flux de données avec une syntaxe concise et expressive, améliorant ainsi la lisibilité et la maintenance du code.
Le ZGC générationnel est une amélioration de l'algorithme de garbage collection (GC) ZGC. Il divise la mémoire en générations pour optimiser la collecte des objets en fonction de leur durée de vie, réduisant ainsi les pauses et améliorant les performances globales des applications.
L'importation de modules est une fonctionnalité clé du système de modules Java (Project Jigsaw). Elle permet de structurer les applications en modules distincts, facilitant ainsi la gestion des dépendances et améliorant la sécurité en encapsulant les composants internes. Cela se traduira en remplaçant les imports *
:
import fr.axopen.com.services.*;
par
import module fr.axopen.com.services;
La fonctionnalité d'exécution de code permet aux développeurs de tester rapidement des snippets de code directement depuis leur environnement de développement, sans avoir à configurer un projet complet. Cela accélère le cycle de développement et facilite l'expérimentation.
La documentation en markdown est une fonctionnalité moderne qui permet de créer des documentations riches et lisibles en utilisant la syntaxe markdown. Elle facilite la création de documents de référence et améliore la collaboration entre les développeurs grâce à une documentation claire et accessible. Voici un exemple donné par openJDK :
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hash tables such as those provided by
* {@link java.util.HashMap}.
* <p>
* The general contract of {@code hashCode} is:
* <ul>
* <li>Whenever it is invoked on the same object more than once during
* an execution of a Java application, the {@code hashCode} method
* must consistently return the same integer, provided no information
* used in {@code equals} comparisons on the object is modified.
* This integer need not remain consistent from one execution of an
* application to another execution of the same application.
* <li>If two objects are equal according to the {@link
* #equals(Object) equals} method, then calling the {@code
* hashCode} method on each of the two objects must produce the
* same integer result.
* <li>It is <em>not</em> required that if two objects are unequal
* according to the {@link #equals(Object) equals} method, then
* calling the {@code hashCode} method on each of the two objects
* must produce distinct integer results. However, the programmer
* should be aware that producing distinct integer results for
* unequal objects may improve the performance of hash tables.
* </ul>
*
* @implSpec
* As far as is reasonably practical, the {@code hashCode} method defined
* by class {@code Object} returns distinct integers for distinct objects.
*
* @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object)
* @see java.lang.System#identityHashCode
*/
/// Returns a hash code value for the object. This method is
/// supported for the benefit of hash tables such as those provided by
/// [java.util.HashMap].
///
/// The general contract of `hashCode` is:
///
/// - Whenever it is invoked on the same object more than once during
/// an execution of a Java application, the `hashCode` method
/// must consistently return the same integer, provided no information
/// used in `equals` comparisons on the object is modified.
/// This integer need not remain consistent from one execution of an
/// application to another execution of the same application.
/// - If two objects are equal according to the
/// [equals][#equals(Object)] method, then calling the
/// `hashCode` method on each of the two objects must produce the
/// same integer result.
/// - It is _not_ required that if two objects are unequal
/// according to the [equals][#equals(Object)] method, then
/// calling the `hashCode` method on each of the two objects
/// must produce distinct integer results. However, the programmer
/// should be aware that producing distinct integer results for
/// unequal objects may improve the performance of hash tables.
///
/// @implSpec
/// As far as is reasonably practical, the `hashCode` method defined
/// by class `Object` returns distinct integers for distinct objects.
///
/// @return a hash code value for this object.
/// @see java.lang.Object#equals(java.lang.Object)
/// @see java.lang.System#identityHashCode
Chez AXOPEN, ce n'est pas un secret, on apprécie beaucoup Java de base ! On pense que c'est l'un des langages les plus fiables sur le long-terme, et c'est d'ailleurs pour ça qu'on s'en sert beaucoup pour le développement d'applications web.
Les nouvelles fonctionnalités de Java représentent une avancée significative pour les développeurs, leur offrant des outils puissants pour écrire du code plus performant, lisible et maintenable. Que ce soit pour la gestion des threads, l'optimisation de la mémoire ou la création de documentations, Java continue de se moderniser pour répondre aux exigences du développement logiciel contemporain et améliorer l'expérience des développeurs !
Java 8 arrive avec une toute nouvelle API Stream qui utilise les Lambda. Cette nouvelle API offre la possibilité de simplifier l’écriture, d’améliorer la performance ainsi d’augmenter la lisibilité d’un certain nombre de code. Nous allons essayer ici de v
Ayant eu quelques difficultés à compiler Jasper Server, je vous propose ici une méthodologie pour compiler les sources Jasper Server tout en évitant les quelques écueils qui ne sont pas détaillés dans la documentation officielle. L’exemple est basé sur un
Java 8 arrive avec une toute nouvelle API Stream qui utilise les Lambda. Cette nouvelle API offre la possibilité de simplifier l’écriture, d’améliorer la performance ainsi d’augmenter la lisibilité d’un certain nombre de code. Nous allons essayer ici de v