Téléchargement

Les informations recueillies dans ce formulaire sont enregistrées dans un fichier informatisé et sont destinées à Metanext pour vous proposer leurs services et offres par téléphone ou courriel. Vos données sont conservées pendant 3 ans. Conformément au RGPD, vous pouvez exercer votre droit d'accès aux données vous concernant et les faire rectifier en contactant conformite@metanext.com. Voir notre Politique de Confidentialité.

Avis d'expert

Avis d'expert Les nouveautés de la JDK 14

par Ahmed CHAARI, Architecte Solutions 

Depuis la version majeure de la jdk9 en septembre 2017 avec les fameux modules, le kit de développement Java entame une marche de livraison soutenue avec une version majeure tous les 6 mois.

Après la version 13 en septembre 2019, la jdk 14 est arrivée le 17 mars 2020, avec son lot de nouveautés.

Dans cet article, nous allons découvrir les principales nouveautés de cette version.

L’amélioration de la NullPointerException

Nous commençons par l’amélioration de la hantise de tout développeur Java : NullPointerException.

Le but de cette nouveauté est de donner plus d’informations aux développeurs en nommant clairement la variable nulle. Ceci va améliorer la compréhension globale de la stack d’erreur mais aussi nous allons pouvoir associer cette exception dynamique à notre code statique.

JFR Event Streaming

L’une des fonctionnalités les plus attendues est l’API JFR Event Streaming.

Rappelons que JFR est l’acronyme de Jdk (ou Java) Flight Recorder : c’est la boîte noire de notre jvm car elle enregistre tous les événements survenus lors de l’exécution de nos applications avec le moins d’impacts possibles sur notre environnement en minimisant l’Observer Effect.

Ainsi, JFR est un outil de profilage et de diagnostic sur les données d’une application Java en cours d’exécution. Ces données collectées peuvent être visualisées et analysées par la Jdk Mission Control comme le montre l’image ci-dessous avec le plugin Eclipse.

Maintenant avec l’API JFR Event Streaming, vous avez la possibilité de consommer de manière continue les événements de la JFR.

Nous tenons à préciser que Datadog a créé un adaptateur pour récupérer les données de la JFR et l’intégrer à leur Tracer. Pour plus d’informations sur ce sujet, rendez-vous au Datadog Java APM : https://github.com/DataDog/dd-trace-java

Le Pattern Matching pour instanceof

Cette fonctionnalité peut paraître comme du sucre syntaxique. Mais derrière cette apparence, il y a une très bonne raison pour justifier son utilisation.

Prenons le code ci-dessous :

if (obj instanceof String) {
    String s = (String) obj;
    // use s
}

Ici vous pouvez rapidement identifier un boilerplate :

  • Tester si obj est de type String,
  • Faire une conversion de obj en String
  • Déclarer un nouvel objet s de type String

La répétition de ce pattern prête à confusion, est propice à l’erreur et multiplie le casting d’objets. Pour remédier à cette situation, la communauté a décidé d’adopter le pattern matching et de rejoindre d’autres langages qui l’utilisent aussi, comme Haskell et C#.

L’opérateur instanceof est étendu afin de gérer les test pattern qui est l’un des types de pattern matching.

En appliquant le pattern à notre code ci-dessus, on obtient le code ci-dessous :

if (obj instanceof String s) {
    // can use s here
} else {
    // can't use s here
}

Pour interpréter ce qui précède, voilà l’enchainement des opérations :

  • L’opérateur instanceof va matcher avec la target obj de type String.
  • Si obj est de type String, il va être casté automatiquement en String et assigné à la variable s.

Maintenant vous pouvez aussi étendre l’utilisation de vos conditions :

if (obj instanceof String s && s.length() > 5) {.. s.contains(..) ..}

if (obj instanceof String s || s.length() > 5) {.. s.contains(..) ..}

Le pattern matching va drastiquement réduire le nombre de casting dans nos programmes.

Prenons le cas de cette fonction :

@Override public boolean equals(Object o) { 
    return (o instanceof CaseInsensitiveString) && 
        ((CaseInsensitiveString) o).s.equalsIgnoreCase(s); 
}

Avec l’utilisation du type test pattern, nous pouvons réécrire cette fonction comme suit :

@Override public boolean equals(Object o) { 
    return (o instanceof CaseInsensitiveString cis) && 
        cis.s.equalsIgnoreCase(s); 
}

Les NVM ou tampons d’octets mappés non-volatils

Le but de ces buffers est d’ajouter de nouveaux modes de mapping des fichiers spécifiques à la jdk.

En d’autres termes, ces nouveaux modes permettront au FileChannel API de créer des MappedByteBuffer qui référencent la mémoire non volatile.

Les expressions switch évoluent

Disons-le, notre switch habituel était source d’erreurs et le break disséminé un peu partout dans notre code le rendait verbeux. Prenons le code suivant :

switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}

Avec cette nouvelle syntaxe et l’introduction de cette forme « case L --> », voilà à quoi ressemblera votre code :

switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}

D’autres écritures évoluent aussi. Prenons l’exemple de ce bout de code :

int numLetters;
switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        numLetters = 6;
        break;
    case TUESDAY:
        numLetters = 7;
        break;
    case THURSDAY:
    case SATURDAY:
        numLetters = 8;
        break;
    case WEDNESDAY:
        numLetters = 9;
        break;
    default:
        throw new IllegalStateException("Wat: " + day);
}

Vous l’avez bien remarqué, notre code est assez verbeux et éclaté. Dorénavant, on peut l’écrire de cette manière :

int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};

D’autres possibilités sont offertes par cette nouvelle syntaxe et pattern. Comme cette fonction howMany :

static void howMany(int k) {
    switch (k) {
        case 1  -> System.out.println("one");
        case 2  -> System.out.println("two");
        default -> System.out.println("many");
    }
}

La disparition du garbage collector CMS

Le garbage collector Concurrent Mark Sweep (CMS) disponible depuis la version 1.4 va disparaître.

Il est remplacé par le garbage collector G1 depuis la JVM 7, le CMS a été déprécié depuis 2 ans avec une baisse du nombre de contributeurs.

Les Records

Les Records est l’une des nouveautés les plus attendues de cette version.

La motivation derrière cette feature est toujours la même : un code moins verbeux. Souvent, nous avons créé des structures de type Classe qui ne sont rien d’autre que des transporteurs de données : data carrier class.

Ces transporteurs étaient dans la majorité des cas négligés par les développeurs. En effet, nous avions à écrire beaucoup de choses : constructeurs, getters, setters, surcharger les méthodes equals(), hashcode() et toString(), …

Les records sont un nouveau type de déclaration dans le langage Java. Comme les Enum, ce sont des formes restrictives de classes. Un record a un nom et une description d’état.

Prenons cet exemple : 

record Range(int lo, int hi) {
  public Range {
    if (lo > hi)  /* referring here to the implicit constructor parameters */
      throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
  }
}

Pour résumer, nous pouvons dire qu’un record est une classe qui ne peut avoir que des variables de type final qui sont initiées dans le constructeur.

Notre record Range remplace ainsi cette classe :

public class Range {
    final int lo;
    final int hi;
    public Range(int lo, int hi) {
        if (lo > hi)  /* referring here to the implicit constructor parameters */
            throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
        this.lo = lo;
        this.hi = hi;
    }
}

Et pour finir, la JDK 15 arrive bientôt …

La jdk 15 est prévue pour septembre 2020 avec une revue publique entre juin et août de la même année.

Pour cette version, les JEP : Java Enhancement Proposals ne sont pas encore fixés. Il y a 18 features candidates parmi lesquelles on peut citer :  la JEP 198 qui portera sur une Light-Weight JSON API, la JEP 301: Enhanced Enums ou bien la JEP 357 qui portera sur la seconde preview du parttern matching pour notre instanceof.

Pour poursuivre cette nouvelle série d’articles, nous aurons  l’occasion prochainement d’aborder certains sujets avec plus de cas pratiques et d’explications mais aussi de creuser les nouveautés de la jdk 15 lorsque les JEP candidates seront bien fixées.

Liens utiles

https://openjdk.java.net/projects/jdk/14/

https://www.infoworld.com/article/3436795/jdk-14-the-new-features-in-Jjva-14.html

https://dzone.com/articles/introducing-java-record

https://www.oracle.com/corporate/pressrelease/oracle-announces-java14-031720.html

https://openjdk.java.net/projects/jdk/15/

 

Vous souhaitez en savoir plus ? 

Contactez-nous

Ressources liées

Transformation IT Vidéo

Méthode d'architecture Metanext avec OpenClassrooms

En savoir plus
Transformation IT Vidéo

Découvrez notre Practice Conseil & Architecture !

En savoir plus
Toutes les ressources
Découvrez les nouvelles fonctionnalités de JDK14!