Qu'attendre de Java en 2020?

2020 est déjà en plein essor, discutons des changements dans le monde Java qui nous attendent cette année. Cet article répertorie les principales tendances de Java et JDK. Et je serai heureux des ajouts des lecteurs dans les commentaires.

Faites immédiatement une réserve sur le fait que l'article est davantage de nature factuelle. Les détails sur chaque sujet abordé peuvent être consultés sur le site Web du projet correspondant ou dans des publications en sources ouvertes.

image

Commençons donc. Malheureusement, vous devrez immédiatement décevoir ceux qui ne suivent pas trop le cycle de sortie de Java, mais qui attendent un long programme de support (LTS). Cette année, nous attendons des versions avec seulement un cycle de vie de support court (STS).
La première, nous considérerons la sortie prochaine de JDK 14, qui devrait sortir à la mi-mars. Dans ce cycle de publication, jusqu'à 16 JEP sont revendiqués. Voici la liste complète:
305:Correspondance de motif pour instanceof (Aperçu)
343:Outil d'emballage (incubateur)
345:Allocation de mémoire compatible avec NUMA pour G1
349:Streaming d'événements JFR
352:Tampons d'octets mappés non volatils
358:NullPointerExceptions utiles
359:Records (Aperçu)
361:Expressions de commutation (standard)
362:Dépréciez les ports Solaris et SPARC
363:Supprimez le garbage collector (CMS) Concurrent Mark Sweep
364:ZGC sur macOS
365:ZGC sur Windows
366:Dépréciez la combinaison ParallelScavenge + SerialOld GC
367:Supprimez les outils et l'API Pack200
368:Blocs de texte (deuxième aperçu)
370:API d'accès à la mémoire étrangère (incubateur)

De nombreux JEP de cette liste ont été largement couverts lors de la conférence Joker 2019. Je me concentrerai sur ceux qui me semblent les plus intéressants.

Correspondance de motif pour instanceof (Aperçu)


Le long JEP sort enfin en Aperçu. Je pense que si vous êtes un programmeur pratiquant qui écrit du code Java depuis de nombreuses années, vous avez rencontré cette douleur plus d'une fois:

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.toUpperCase());
}

Si vous avez écrit ou écrivez du code également dans Kotlin, alors la douleur de voir le code Java est un peu pire. Les participants au projet Amber nous présenteront leur vision de Pattern Matching en Java, qui devrait réduire cette douleur. Avec l'avènement de Java 14, nous pouvons réécrire l'exemple comme suit:

if (obj instanceof String s) {
   System.out.println(s.toUpperCase());
}

Il semble que le module complémentaire ne soit pas si précieux - nous enregistrons une ligne de code. Mais supposons que nous voulions faire ce qui suit:

if (obj instanceof String) {
    String s = (String) obj;
    if (s.contains(“prefix_”)) {
       return s.toUpperCase();
    }
}
return null;

Ça a l'air encombrant, non? Essayons la même chose, mais avec Pattern Matching.

return (obj instanceof String s) && s.contains(“prefix_”) ? s.toUpperCase() : null;

Alors, évidemment, ce sera mieux. Mais rappelez-vous que le statut de cette fonctionnalité est Aperçu. Voyons ce qui change avec le temps. Pour moi, cela rendra certainement ma vie meilleure.

NullPointerExceptions utiles


2020 est dans la cour, et vous écrivez toujours pour que les NullPointerExceptions s'envolent pour vous? Ne vous inquiétez pas, vous n'êtes probablement pas le seul. Goetz Lindenmaier et Ralf Schmelter n'ont pas suggéré de nouvelle façon de s'éloigner des NullPointerExceptions (facultatif est toujours avec nous), mais ils ont proposé d'améliorer le processus de débogage de l'application pour comprendre exactement où se trouve null. Imaginons donc que nous écrivions le code à cinq heures ... la nuit, bien sûr. Et nous avons écrit cette fonction:

public String getStreetFromRequest(Request request) {
   return request.getAddress().getStreet().toUpperCase();
}

Pas mal, mais ils ont complètement oublié de mettre les annotations @Nullable et @Nonnull et de vérifier l'adresse dans les champs transmis. Vous avez une NullPointerException. Que nous dit l'exception?

Exception in thread "main" java.lang.NullPointerException
	at Program.getStreetFromRequest(Program.java:10)
	at Program.main(Program.java:6)

Hélas, nous ne voyons qu'une ligne, une classe et une pile. Où est exactement revenu null? C'est peut-être une demande? Peut-être que getAddress () a retourné null? Ou peut-être getStreet ()? Eh bien, les chaînes d'appel font parfois mal.

Les auteurs de JEP proposent une solution: lors du lancement d'une exception, il est censé contourner la pile pour déterminer où exactement null est retourné, puis afficher le nom des variables / méthodes. Essayons Java 14 avec l'option -XX: + ShowCodeDetailsInExceptionMessages. Nous commençons et obtenons un peu différent:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.toUpperCase()" because the return value of "Address.getStreet()" is null
	at Program.getStreetFromRequest(Program.java:10)
	at Program.main(Program.java:6)

Maintenant, nous savons que la programmation de nuit n'améliore pas (mais conduit parfois à l'achèvement des tâches à temps), et dans notre programme, nous avons oublié que l'adresse n'est pas un champ obligatoire.

Records (Aperçu)


Toujours générer des getters / setters / equals / hashCode avec une idée? Alors ce JEP vient à vous!
Les classes de données sont loin d'être la dernière place dans la vie d'un développeur de logiciels d'application. Chaque fois, nous devons soit générer des méthodes de classes de données en utilisant notre IDE préféré, soit utiliser divers plugins au moment de la compilation pour générer les méthodes nécessaires, telles que lombok.

En conséquence, nous avons beaucoup de code similaire à ceci:

public class Request {
    private Address address;

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
       this.address = address;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Request request = (Request) o;
        return Objects.equals(address, request.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(address);
    }

    @Override
    public String toString() {
        return "Request{" +
                "address=" + address +
                '}';
    }
}

Ou tel:
@Data
@AllArgsConstructor
public class Request {
    private Address address;
}

En Java 14, les membres du projet Amber proposent une nouvelle syntaxe pour créer des classes de données. Pour ce faire, utilisez le nouvel enregistrement de mot-clé. La syntaxe de Record est légèrement différente de celle des descriptions de classe ou de l'énumération, et est légèrement similaire à Kotlin. Le code ci-dessus peut être réécrit comme suit:

public record Request(Address address) {
}

Tous les champs d'enregistrement ont des modificateurs privés et finaux par défaut. L'enregistrement lui-même est une classe finale et ne peut pas être hérité d'une autre classe, mais il peut implémenter des interfaces. Dans les classes d'enregistrement de la boîte, nous obtenons: les méthodes getters, un constructeur public, dont les paramètres sont tous des champs d'enregistrement dans l'ordre de description, égal à / hashCode et toString. Du désagréable: nous ne pouvons pas ajouter de champs à l'enregistrement, sauf ceux spécifiés après le nom de la classe. Par exemple, ce code entraînera une erreur:

public record Request(Address address) {
   private final String anotherParameter; // compilation error
}

Blocs de texte (deuxième aperçu)


Les blocs de texte ont été libérés sous forme d'aperçus dans Java 13. Nous, les utilisateurs, avons tordu, tourné et donné notre avis (je crois sincèrement que vous utilisez déjà Java 13 avec aperçu). En conséquence, les créateurs Java ont apporté des modifications mineures aux blocs de texte. Tout d'abord, nous pouvons maintenant indiquer explicitement où se termine la ligne, en mettant la séquence d'échappement dans notre ligne. Voici un exemple:

public static void main(String[] args) {
        final var test = """
                This is the long text block with escape string \s
                that is really well done            \s
                """;
        System.out.println(test);
}

Maintenant, nous définissons explicitement tous les espaces sur le caractère \ s et tous les caractères d'espace seront enregistrés sur le caractère \ s.

Deuxièmement, nous pouvons maintenant encapsuler de longues lignes d'un bloc de texte sans recevoir \ n de caractères dans la dernière ligne. Pour ce faire, il suffit d'ajouter \ au saut de ligne. À quoi cela ressemble-t-il:

public static void main(String[] args) {
        final var test = """
                This is the long text block with escape string \
                that is really well-done functional            
                """;
System.out.println(test);

Après l'exécution, nous obtenons la ligne suivante: «C'est le long bloc de texte avec chaîne d'échappement qui est vraiment bien fait».

Un bon ajout, il me semble. J'ai vraiment hâte de traduire cette fonctionnalité en standard.
Toutes les fonctionnalités que nous avons examinées sont susceptibles d'être largement discutées lors des prochaines conférences. Certains d'entre eux ont déjà été discutés lors du Joker 2019. N'oubliez pas de consulter la conférence Joker 2019 sur «L'évolution des fonctionnalités dans Java 13 et au-delà» par Cay Horstmann.

Et des choses plus intéressantes.


Il y a deux éléments intéressants sur la liste JEP dans l'incubateur. Pour commencer, nous aurons un outil universel qui créera des installateurs pour différents systèmes d'exploitation (enfin, je veux dire à ceux qui ont dansé autour de l'installation de programmes sur Windows). Jpacker pourra créer des installateurs msi / exe pour Windows, des packages macOS et rpm / deb pour Linux. Voyons ce qui en résulte, mais dans ces rares cas où j'ai fait quelque chose pour le bureau, j'ai personnellement souffert du fait que je n'avais pas d'outil régulier pour assembler le programme d'installation.

Encore plus prometteur est la nouvelle API pour accéder à la «mémoire étrangère», c'est-à-dire tout type de mémoire native ou persistante. Cette API est principalement utile pour les créateurs de bases de données Java ou les créateurs de framework tels que Netty, par exemple. Ils, en utilisant Unsafe et ByteBuffer, optimisent autant que possible l'accès à la mémoire avec hors-tas.

Prochaine version. Joie et frustration


En septembre, nous attendons une autre version de support à court terme au numéro 15. La liste des JEP qui seront inclus dans la version finale est toujours ouverte. Jusqu'à présent, vous pouvez voir beaucoup de changements différents dans le langage lui-même, dans la bibliothèque standard et la machine virtuelle.
Voici la liste des candidats (elle peut changer rapidement, regardez ici: bugs.openjdk.java.net/secure/Dashboard.jspa?selectPageId=19114 ):
111:Additional Unicode Constructs for Regular Expressions
116:Extended Validation SSL Certificates
134:Intuitive Semantics for Nested Reference Objects
152:Crypto Operations with Network HSMs
198:Light-Weight JSON API
218:Generics over Primitive Types
300:Augment Use-Site Variance with Declaration-Site Defaults
301:Enhanced Enums
302:Lambda Leftovers
303:Intrinsics for the LDC and INVOKEDYNAMIC Instructions
306:Restore Always-Strict Floating-Point Semantics
338:Vector API (Incubator)
339:Compiler Intrinsics for Java SE APIs
348:Compiler Intrinsics for Java SE APIs
356:Enhanced Pseudo-Random Number Generators
360:Sealed Types (Preview)
371:Hidden Classes

Comme vous pouvez le voir, la liste n'a toujours pas beaucoup de choses attendues. Tout d'abord, pour moi, c'est Project Loom. L'idée de parallélisme structurel a été très populaire ces dernières années. Les coroutines peuvent grandement simplifier la tâche de l'informatique parallèle compétitive et de l'exécution asynchrone des tâches. De grands exemples de mise en œuvre de cette idée peuvent être vus, par exemple, dans les langues Kotlin (coroutines) et Go (goroutines). Java explore également l'idée du parallélisme structurel, et il y a déjà des premiers résultats. Pour l'instant, vous ne pouvez les voir qu'en compilant le JDK à partir du référentiel de projet.

Un projet très prometteur Valhalla ne nous a également pas encore satisfaits avec des aperçus. Un rapport intéressant sur ce projet a été présenté au Joker 2019 ("Est-ce que Java nécessite des types" en ligne "? Une vue étroite de l'ingénieur de la performance sur le projet Valhalla" par Sergey Kuksenko).

Qu'est-ce qui est présenté dans la liste?

La première chose qui attire votre attention est l'API JSON. La question se pose immédiatement - pourquoi? Il n'y a manifestement pas de réponse définitive. La section JEP sur la motivation dit que JSON est devenu quelque chose de standard pour les services Web, et maintenant il est temps d'adapter Java SE pour interagir avec JSON (même s'il existe une tonne de bibliothèques pour analyser JSON maintenant). L'explication la plus probable est la possibilité pour les développeurs de logiciels d'utiliser une petite API de base pour réduire la taille du bundle sans avoir à traîner le lourd Jackson à eux-mêmes. Je ne vois aucune autre explication, car il n'aura même pas de liaison de données.

Nous constatons également un certain nombre d'améliorations liées à l'API cryptographique. Pour commencer, les développeurs JDK souhaitent étendre le processus de validation des certificats SSL en ajoutant la prise en charge des certificats EVSSL. En utilisant cette API en Java, vous pouvez déterminer si une connexion SSL est approuvée par un certificat EV (Extended Validation). Le certificat EVSSL conformément à la directive sera entièrement pris en charge. Un nouvel algorithme cryptographique EdDSA sera également ajouté et la vérification de la cryptographie HSM sera améliorée.

Du langage, je soulignerais l'implémentation de Generics sur les primitives. Quiconque a déjà programmé en C # et est passé à Java pourrait probablement se demander pourquoi il est impossible de faire des types génériques sur des primitives. La réponse est simple: les génériques ne fonctionnent qu'avec des objets, et les primitives ne sont pas des objets et, en particulier, n'héritent pas d'une classe Object. Ce n'est pas la première année qu'une guerre est menée sur cette question, et Brian Goetz y revient à nouveau. Il n'y a rien de spécial à décrire jusqu'à présent. La tâche est claire: prendre en charge des constructions telles que List. Mais même en ce moment, il reste 13 questions ouvertes à résoudre avant de mettre en œuvre cette fonctionnalité. Honnêtement, je me demande comment cette série se terminera.

Et la dernière chose que je veux aborder, ce sont les types scellés. Il s'agit de la prochaine étape vers la correspondance de motifs. Sealed Types est une extension de langage qui implémente le scellé (modificateur) et autorise les mots-clés pour une classe ou une interface.

En utilisant la classe scellée, nous limitons le nombre de descendants aux seules classes spécifiées dans les permis (une restriction explicite) ou dans la même unité de compilation (fichier). Exemple de description d'une classe scellée:

// 
public abstract sealed class Base {
   public static class ChildA extends Base{}
   public static class ChildB extends Base{}
}

// 
public sealed interface BaseInterface permits ChildC, ChildD{
}

//  
public class ChildC implements BaseInterface {
}
//  
public class ChildD implements BaseInterface {
}

Le modificateur scellé garantit que seul un ensemble limité de descendants peut étendre la classe de base ou implémenter une interface. Cette propriété peut être utilisée lors du traitement des objets de ces classes. Et, bien sûr, c'est un excellent candidat à utiliser dans une instruction switch avec correspondance de modèle.

Conclusion


Nous avons examiné les différentes innovations JDK cette année. Certains tireront, d'autres non. Mais surtout dans les nouveaux JDK, j'attends de nouvelles petites (ou pas) optimisations qui rendent nos programmes plus rapides avec chaque version gratuite. Et si vous étiez au dernier Joker 2019 et avez visité le rapport de Tagir Valeev Java 9-14: Petites optimisations, alors très probablement, comme moi, vous avez été impressionné par le travail que les contributeurs font pour optimiser JDK. Ses résultats ne sont pas visibles à première vue et ne se reflètent pas dans plus d'un JEP, mais nous les utilisons tous les jours.

De bonnes versions Java pour nous tous. Explorez les nouvelles fonctionnalités de la plateforme, allez à des conférences et suivez les tendances.

All Articles