Java 23 est prévu pour Septembre 2024. Un build d'Early Access est cependant déjà disponible au téléchargement. Il contient, en version préliminaire, une JEP intéressante traitant des types primitifs dans les motifs de recherche.
JEP 455 : Primitive Types in Patterns
Cette JEP nous propose d'étendre les Pattern Matching introduits dans Java 17 aux types primitifs.
Comment tester facilement la version Early Access ?
Depuis Java 21, il est extrêmement facile de tester un bout de code Java, sans avoir à le compiler au préalable.
On télécharge Java 23 : https://jdk.java.net/23/
Et il suffit d'écrire le code suivant dans un fichier nommé Main.java, sans nécessiter la déclaration 'public class Main' :
void main(){
System.out.println("Hello World");
}
On exécute ensuite la classe, en activant les previews :
C:\chemin\vers\jdk\bin\java.exe --enable-preview Main.java
Hello World
Rappel sur les Pattern Matching
Introduits dans Java 17, les Pattern Matching apportent une grande flexibilité lorsqu'on définit les conditions de typage dans un if ou dans un switch.
Dans un if :
public String toString(Object o){
if(o instanceof LocalDate l){
return l.format(DateTimeFormatter.ISO_DATE);
}
return o.toString();
}
On définit dynamiquement le nom de la variable qui correspond au type spécifié par "instanceof", évitant ainsi un cast explicite.
Examinons maintenant l'utilisation de cette fonctionnalité dans une structure switch :
public double area(Shape shape){
return switch (shape){
case Rectangle r -> r.height * r.height;
case Circle c when c.radius > 0 -> 2 * Math.PI * c.radius;
case Circle _ -> 0;
};
}
Le switch porte sur le type de Shape (qui est une sealed interface). On remarque ici l'utilisation d'un guard avec le mot clé when, ainsi que l'utilisation de _ en pattern anonyme.
En Java 22, ces Pattern sur type ne vont pas fonctionner avec des types primitifs.
Primitive Pattern Matching
La JEP 455 nous propose de résoudre le problème des types primitifs :
public String giveStatus(int status){
return switch (status) {
case 0 -> "okay";
case 1 -> "warning";
case 2 -> "error";
case int i -> STR."unknown status: \{i}";
};
}
Cette possibilité était déjà existante via l'usage d'une instruction case default
. Toutefois, la JEP propose d'aller bien au-delà en simplifiant substantiellement la conversion des types primitifs. La conversion d'un int
en long
est, en effet, relativement simple, mais le processus inverse est plus périlleux et susceptible d'entraîner une perte de données. Afin de pallier ce risque, voici une méthode permettant de sécuriser ces conversions.
public static void fillPrimitive(Structure s, double d){
switch (d){
case byte b -> s.setByte(b);
case int i -> s.setInt(i);
case float f -> s.setFloat(f);
default -> s.setDouble(d);
}
}
Dans ce cas, les conversions sont à la fois sûres et précises. En effet, le case byte
ne sera appliqué que si la valeur de d
se situe entre -128 et 127, représentant ainsi un entier compatible avec le type byte
.
Conclusion
Cette première fonctionnalité en preview apportée par Java 23 propose non seulement d'étendre les Pattern Matching aux types primitifs, mais également de rendre les conversions entre primitifs très simples et sûres.