3 pièce(s) jointe(s)
Java 14 est disponible en version définitive avec de nouvelles fonction de productivité des développeurs
La version stable du Java Developpement Kit 14 est prévue pour février 2020,
petit aperçu de fonctionnalités en préversion
Le cycle de sortie de Java a changé de façon assez profonde récemment, ce qui signifie que nous obtenons de nouvelles fonctionnalités à un rythme plus rapide qu'auparavant. Aujourd'hui nous parlerons de deux fonctionnalités intéressantes du langage.
Améliorations au niveau du switch
Selon certains professionnels, l'instruction switch classique en Java n'est pas géniale. Contrairement à de nombreuses autres parties de Java, elle n'a pas été correctement repensée lors du retrait des fonctionnalités de C il y a toutes ces années. Le défaut clé est la "chute par défaut". Cela signifie que si vous oubliez de mettre une clause break dans chaque cas, le traitement se poursuivra jusqu'à la clause case suivante.
Un autre défaut est que les variables sont étendues à l'intégralité du switch, vous ne pouvez donc pas réutiliser un nom de variable dans deux clauses case différentes. De plus, une clause par défaut n'est pas requise, ce qui laisse les lecteurs du code dans l'incertitude quant à savoir si une clause a été ou non oubliée.
Et bien sûr, il y a aussi la principale limitation - le type à activer ne peut être qu'un entier, une énumération ou une chaîne.
Code:
1 2 3 4 5 6 7 8 9 10 11 12
| String instruction;
switch (trafficLight) {
case RED:
instruction = "Stop";
case YELLOW:
instruction = "Prepare";
break;
case GREEN:
instruction = "Go";
break;
}
System.out.println(instruction); |
Le code ci-dessus ne se compile pas, car il n'y a pas de clause default par défaut, laissant instruction indéfinie. Mais même s'il compilait, il n'imprimerait jamais "Stop" en raison du break manquant.
Dans le cadre du Project Amber, switch a bénéficié de quelques changements ! Ils ont été lancés en préversion dans JDK 12 et à nouveau dans 13 et sont au moment de la rédaction destinés à être publiés dans JDK 14. Les développeurs vont disposer d'une nouvelle fonctionnalité lorsque switch sera utilisé comme instruction. En outre, il pourra également être utilisé comme une expression à l'avenir.
Bienvenue case X ->
Dans la syntaxe de switch, il est désormais possible de se servir de case X -> en plus du traditionnel case X:. Dans ces cas d'utilisations, seule l'expression ou l'instruction sur le côté droit de la flèche sera exécutée. Cela signifie que vous n'aurez plus besoin de vous rappeler d'utiliser break pour sortir du switch dès lors qu'une languette va correspondre.
Code:
1 2 3 4 5 6
| String quantityString;
switch (n) {
case 1 -> quantityString = "one";
case 2 -> quantityString = "two";
default -> quantityString = "many";
} |
Expressions switch
switch peut désormais être utilisé comme expressions, c'est-à-dire qu'il peut retourner une valeur. Cela signifie que nous n'aurons pas à déclarer d'abord une variable, puis à affecter une valeur dans chaque branche. Combiné avec des étiquettes de flèche, il nous permet d'exprimer notre intention en beaucoup moins de lignes de code:
Code:
1 2 3 4 5
| String quantityString = switch (k) {
case 1 -> "one";
case 2 -> "two";
default -> "many";
}; |
Parfois, vous pourriez être obligé d'exécuter un bloc de code dans le cadre d'une expression de cas. Afin de combiner cela avec la syntaxe d'étiquette de flèche, vous devez yield une valeur à la fin du bloc:
Code:
1 2 3 4 5 6 7 8
| DayType type = switch (day) {
case 1, 2, 3, 4, 5 -> WEEKDAY;
case 6, 7 -> WEEKEND;
default -> {
logger.warn(day + " is not a valid day. Legal values are [1..7]");
yield UNKNOWN;
}
}; |
Vous pouvez également transformer les switch d'instruction en expression à l'aide des anciennes étiquettes de style en vous servant de yield.
Code:
1 2 3 4 5 6 7 8 9
| Type type = switch (day) {
case 1, 2, 3, 4, 5:
yield WEEKDAY;
case 6, 7:
yield WEEKEND;
default:
logger.warn(day + " is not a valid day.");
yield UNKNOWN;
}; |
N'oubliez pas que c'est la syntaxe des libellés fléchés qui empêche les chutes. Cela signifie que si vous oubliez de yield, l'expression de cas suivante sera évaluée et vous pourriez vous retrouver avec le mauvais résultat.
Qu'en pensent les professionnels ?
Le développeur Stephen Colebourne s'est laissé aller à un billet où il soulève quelques questions importantes concernant l'UX de ces fonctionnalités.
« Je ne suis pas convaincu des mérites du nouveau design. Pour être clair, il y a de bons aspects, mais dans l'ensemble, je pense que la solution est trop complexe et avec des choix de syntaxe désagréables.
« L'objectif principal est d'ajouter un formulaire d'expression, où vous pouvez affecter le résultat du switch à une variable. C'est un peu comme l'opérateur ternaire (par exemple. x != Null ? x : ""), qui est l'équivalent d'expression d'une instruction if. Une forme d'expression réduirait les problèmes comme la variable non définie ci-dessus, car elle rend plus évident que chaque branche doit entraîner une variable.
« Le plan actuel consiste à ajouter non pas une, mais trois nouvelles formes de commutation. Oui, trois.
- Type 1: déclaration avec syntaxe classique. Comme aujourd'hui. Avec fall-through-by-default. Pas exhaustive.
- Déclaration
- Fall-through-by-default
- retour autorisé, également continue / break une boucle
- Portée unique pour les variables
- La logique pour chaque cas est une séquence d'instructions pouvant se terminer par yield
- Non exhaustif - une clause par défaut n'est pas requise
- yieldle rendement n'est pas autorisé
- Type 2: Expression avec une syntaxe classique. NOUVEAU! Avec fall-through-by-default. Doit être exhaustive.
- Expression
- Fall-through-by-default
- retour non autorisé, impossible de continue / break une boucle
- Portée unique pour les variables
- La logique pour chaque cas peut être une expression de rendement ou une séquence d'instructions se terminant potentiellement par yield
- Exhaustive - une clause par défaut est requise
- Doit utiliser yield pour renvoyer des valeurs
- Type 3: instruction avec nouvelle syntaxe. NOUVEAU! Pas de fall-through. Pas exhaustive.
- Déclaration
- L'interruption n'est pas autorisée
- retour autorisé, ainsi que continue / break sur une boucle
- aucun problème de portée variable, la logique pour chaque cas doit être une instruction ou un bloc
- Non exhaustif - une clause par défaut n'est pas requise
- yield n'est pas autorisé
- Type 4: Expression avec une nouvelle syntaxe. NOUVEAU! Pas de fall-through. Doit être exhaustive.
- Expression
- L'interruption n'est pas autorisée
- retour non autorisé, impossible de continue / break une boucle
- Aucun problème de portée variable, la logique pour chaque cas doit être une expression ou un bloc se terminant par yield
- Exhaustive - une clause par défaut est requise
- Doit utiliser yield pour renvoyer des valeurs, mais uniquement à partir de blocs (c'est implicite quand ce n'est pas un bloc)
Voici un exemple de type 4
Code:
1 2 3 4 5 6 7
| // type 4
var instruction = switch (trafficLight) {
case RED -> "Stop";
case YELLOW -> "Prepare";
case GREEN -> "Go";
};
System.out.println(instruction); |
« Comme on peut le voir, la nouvelle syntaxe de type 3 et 4 utilise une flèche au lieu d'un deux-points. Et il n'est pas nécessaire d'utiliser break si le code se compose d'une seule expression. Il n'y a pas non plus besoin d'une clause par défaut lors de l'utilisation d'une énumération, car le compilateur peut l'insérer pour vous à condition que vous ayez inclus toutes les valeurs énumérées connues. Donc, si vous avez raté GREEN, vous obtiendrez une erreur de compilation.
« Le diable est bien sûr dans le détail.
« Premièrement, un point clairement positif. Au lieu de passer à travers en listant plusieurs étiquettes, elles peuvent être séparées par des virgules :
Code:
1 2 3 4 5 6
| // type 4
var instruction = switch (trafficLight) {
case RED, YELLOW -> "Stop";
case GREEN -> "Go";
};
System.out.println(instruction); |
« Simple et évident. En plus d'éviter de nombreux cas d'utilisation simples de sortie. Et si le code à exécuter est plus complexe qu'une expression ?
Ce qu'il dit de tout cela ?
« Les expressions switchde commutateur de type 4 sont correctes (bien que j'ai de réels problèmes avec l'extension de la syntaxe des flèches à partir de lambdas). Mon problème est avec les types 2 et 3. En réalité, ces deux types de switch seront très rares, et donc la plupart des développeurs ne les verront jamais. Compte tenu de cela, je pense qu'il serait préférable de ne pas les inclure du tout. Une fois que cela est accepté, il ne sert à rien de traiter les formes d'expressions comme un switch, car il n'aura en réalité pas beaucoup de connexions avec l'ancienne forme de déclaration. Je laisserais tomber les types 2 et 3 et autoriserais les expressions switch de type 4 à devenir ce qu'on appelle des expressions de déclaration.
Code:
1 2 3 4 5 6 7 8 9 10 11 12
| // Stephen's expression switch
var instruction = match (trafficLight) {
case RED: "Stop";
case YELLOW: "Prepare";
case GO: "Go";
}
// Stephen's expression switch used as a statement (technically a statement expression)
match (instruction) {
case "Stop": doStop();
case "Go": doGo();
default: ;
} |
« Si vous ignorez la complexité et utilisez simplement des expressions switch de type 4, la nouvelle fonctionnalité est tout à fait raisonnable. Cependant, afin d'ajouter la seule forme de switch nécessaire à Java, nous devons également prendre en considération les deux autres ratés - type 2 et 3. À mon avis, la fonctionnalité doit revenir à la planche de travail, mais malheureusement je soupçonne que c'est maintenant trop tard pour ça ».
Correspondance de modèle pour instanceof
En tant que développeur Java, vous avez probablement été dans une situation où vous devez vérifier si un objet est d'un certain type, et si c'est le cas - le caster dans ce type. Ce modèle est largement utilisé par exemple dans les implémentations equals.
Introduit en tant que fonctionnalité en préversion dans JDK 14, instanceof est étendu pour prendre ce qu'on appelle un modèle de test de type au lieu d'un simple type. Un modèle de test de type se compose d'un prédicat et d'une variable de liaison.
Prenons cet exemple :
Code:
1 2 3 4 5 6 7 8
| @Override
public boolean equals(Object obj) {
if (obj instanceof Person) {
Person other = (Person) obj;
return this.name == other.name;
}
return false;
} |
En utilisant cette nouvelle fonctionnalité, vous pouvez réécrire le code comme suit:
Code:
1 2 3 4 5 6 7
| @Override
public boolean equals(Object obj) {
if (obj instanceof Person other) {
return this.name == other.name;
}
return false;
} |
Dans l'exemple ci-dessus, Person other est le modèle de test de type.
Dans le bloc if, vous pouvez utiliser other et il est garanti qu'il s'agit d'une Person. En revanche, other n'est pas accessible en dehors du bloc if.
Code:
1 2 3 4 5
| if (!(obj instanceof String s)) {
System.out.println(s); // 1
} else {
System.out.println(s); // 2
} |
Comment activer les fonctionnalités en préversion ?
Les nouveaux changements switch ont actuellement le drapeau préversion dans la version JDK la plus récente (13). Cela signifie que vous ne devez probablement pas les utiliser dans une large mesure dans la base de code qui constitue votre gagne-pain. Les API peuvent changer et il y a toujours une chance que la fonctionnalité ne soit pas promue en fonction stable dans sa forme actuelle.
Il est cependant utile de les expérimenter. Essayer de nouvelles fonctionnalités est un bon moyen d'élargir votre ensemble de compétences, et s'il y a quelque chose que vous n'aimez pas du tout quant à la convivialité d'une fonctionnalité, vous pouvez même fournir des commentaires aux développeurs JDK.
Pour commencer à expérimenter les préversions de ces fonctionnalités sur l'outil dont vous vous servez, il vous suffit de suivre les instructions ci-dessous:
Maven
Pour activer pendant la compilation, ajoutez la configuration suivante à maven-compiler-plugin:
Code:
1 2 3 4 5 6
| <configuration>
<release>13</release>
<compilerArgs>
--enable-preview
</compilerArgs>
</configuration> |
Pour l'exécution du test, ajoutez la configuration suivante à maven-surefire-plugin et / ou maven-fail-safe-plugin:
Code:
1 2 3
| <configuration>
<argLine>--enable-preview</argLine>
</configuration> |
Gradle
Activez l'indicateur du compilateur pour la compilation et l'exécution des tests comme suit:
Code:
1 2 3 4 5 6
| compileJava {
options.compilerArgs += ["--enable-preview"]
}
test {
jvmArgs '--enable-preview'
} |
IntelliJ
Accédez à Paramètres du projet> Projet et recherchez la liste déroulante Niveau de langage du projet. Si vous avez précédemment ciblé la version 13 et que vous souhaitez activer les fonctionnalités en préversion, choisissez 13 (Preview).
Sources : billet Stephen Colebourne, OpenJDK (switch, instanceOf)
Voir aussi :
:fleche: Vaudra-t-il encore la peine de consacrer du temps à l'étude du langage Java en 2020 ? Voici 10 raisons de répondre à l'affirmative, selon l'éditeur du blog Javarevisited
:fleche: L'extrait de code Java le plus copié sur Stack Overflow contient un bogue et son auteur, Andreas Lundblad, développeur Java chez Palantir, propose un correctif
:fleche: Entre Java et Kotlin, lequel de ces langages est le meilleur pour le développement d'applications Android ?
:fleche: SQL et Java sont encore les compétences techniques les plus demandées en 2019, selon un rapport d'étude
2 pièce(s) jointe(s)
JDK 14 va apporter plus de fonctionnalités que les deux versions précédentes combinées
JDK 14 va apporter plus de fonctionnalités que les deux versions précédentes combinées,
petit tour d'horizon de celles qui sont susceptibles d'intéresser le plus les développeurs
La sortie de JDK 14 est prévue pour le 17 mars. La version 14 comprend plus de JEP (Java Enhancement Proposals) que JDK 12 et 13 combinés. Qu'est-ce qui pourrait être le plus intéressant pour les développeurs Java qui écrivent et maintiennent du code au quotidien ? Dans un billet de blog, Raoul-Gabriel Urma, PDG et cofondateur de Cambridge Spark, a abordé quelques points :
- des améliorations au niveau des expressions switch, qui sont apparues pour la première fois dans Java 12 et Java 13 en tant que préversion et font désormais partie intégrante de Java 14 ;
- le pattern matching pour instanceof (une fonction de langage)
- Des NullPointerExceptions utiles (une fonctionnalité JVM)
Selon certains professionnels, l'instruction switch classique en Java n'est pas géniale. Contrairement à de nombreuses autres parties de Java, elle n'a pas été correctement repensée lors du retrait des fonctionnalités de C il y a toutes ces années. Le défaut clé est la « chute par défaut ». Cela signifie que si vous oubliez de mettre une clause break dans chaque cas, le traitement se poursuivra jusqu'à la clause case suivante.
Un autre défaut est que les variables sont étendues à l'intégralité du switch, vous ne pouvez donc pas réutiliser un nom de variable dans deux clauses case différentes. De plus, une clause par défaut n'est pas requise, ce qui laisse les lecteurs du code dans l'incertitude quant à savoir si une clause a été ou non oubliée.
Et bien sûr, il y a aussi la principale limitation : le type à activer ne peut être qu'un entier, une énumération ou une chaîne.
Dans le cadre du Project Amber, switch a bénéficié de quelques changements ! Ils ont été lancés en préversion dans JDK 12 et à nouveau dans 13 et sont destinés à être publiés dans JDK 14. Les développeurs vont disposer d'une nouvelle fonctionnalité lorsque switch sera utilisé comme instruction. En outre, il pourra également être utilisé comme une expression à l'avenir.
Les avantages des nouvelles expressions switch incluent une portée réduite pour les bogues en raison de l'absence de comportement de transition, l'exhaustivité et la facilité d'écriture grâce à l'expression et à la forme composée. À titre d'exemple de mise à jour, une expression switch peut désormais tirer parti de la syntaxe ->, comme dans cet exemple:
Code:
1 2 3 4 5 6 7 8 9 10
| var log = switch (event) {
case PLAY -> "User has triggered the play button";
case STOP, PAUSE -> "User needs a break";
default -> {
String message = event.toString();
LocalDateTime now = LocalDateTime.now();
yield "Unknown event " + message +
" logged on " + now;
}
}; |
Il faut noter également que switch peut désormais être utilisé comme expressions, c'est-à-dire qu'il peut retourner une valeur. Cela signifie que nous n'aurons pas à déclarer d'abord une variable, puis à affecter une valeur dans chaque branche. Combiné avec des étiquettes de flèche, il nous permet d'exprimer notre intention en beaucoup moins de lignes de code:
Code:
1 2 3 4 5
| String quantityString = switch (k) {
case 1 -> "one";
case 2 -> "two";
default -> "many";
}; |
Parfois, vous pourriez être obligé d'exécuter un bloc de code dans le cadre d'une expression de cas. Afin de combiner cela avec la syntaxe d'étiquette de flèche, vous devez yield une valeur à la fin du bloc:
Code:
1 2 3 4 5 6 7 8
| DayType type = switch (day) {
case 1, 2, 3, 4, 5 -> WEEKDAY;
case 6, 7 -> WEEKEND;
default -> {
logger.warn(day + " is not a valid day. Legal values are [1..7]");
yield UNKNOWN;
}
}; |
Vous pouvez également transformer les instructions switch en expressions à l'aide des anciennes étiquettes de style en vous servant de yield.
Code:
1 2 3 4 5 6 7 8 9
| Type type = switch (day) {
case 1, 2, 3, 4, 5:
yield WEEKDAY;
case 6, 7:
yield WEEKEND;
default:
logger.warn(day + " is not a valid day.");
yield UNKNOWN;
}; |
N'oubliez pas que c'est la syntaxe des libellés fléchés qui empêche les chutes. Cela signifie que si vous oubliez de yield, l'expression de cas suivante sera évaluée et vous pourriez vous retrouver avec le mauvais résultat.
Blocs de texte
Java 13 a introduit des blocs de texte comme fonction en préversion. Les blocs de texte facilitent le travail avec les littéraux de chaînes multilignes. Cette fonctionnalité est de nouveau en préversion sur Java 14 et intègre quelques ajustements. En guise de rappel, il est assez courant d'écrire du code avec de nombreuses concaténations de chaînes et séquences d'échappement afin de fournir une mise en forme de texte multiligne adéquate. Le code ci-dessous montre un exemple de mise en forme HTML:
Code:
1 2 3 4 5
| String html = "<HTML>" +
"\n\t" + "<BODY>" +
"\n\t\t" + "<H1>\"Java 14 is here!\"</H1>" +
"\n\t" + "</BODY>" +
"\n" + "</HTML>"; |
Avec les blocs de texte, vous pouvez simplifier ce processus et écrire du code plus élégant à l'aide des trois guillemets qui délimitent le début et la fin d'un bloc de texte:
Code:
1 2 3 4 5 6
| String html = """
<HTML>
<BODY>
<H1>"Java 14 is here!"</H1>
</BODY>
</HTML>"""; |
Les blocs de texte offrent également une plus grande expressivité par rapport aux littéraux de chaîne normaux.
Deux nouvelles séquences d'échappement ont été ajoutées dans Java 14. Premièrement, vous pouvez utiliser la nouvelle séquence d'échappement \s pour signifier un seul espace. Deuxièmement, vous pouvez utiliser une barre oblique inverse, \, comme moyen de supprimer l'insertion d'un nouveau caractère de ligne à la fin d'une ligne. Ceci est utile lorsque vous avez une très longue ligne que vous souhaitez diviser pour plus de lisibilité à l'intérieur d'un bloc de texte.
Par exemple, la façon actuelle de faire des chaînes multilignes est :
Code:
1 2 3 4
| String literal =
"Lorem ipsum dolor sit amet, consectetur adipiscing " +
"elit, sed do eiusmod tempor incididunt ut labore " +
"et dolore magna aliqua."; |
Avec la séquence d'échappement \ dans des blocs de texte, cela peut s'exprimer comme suit:
Code:
1 2 3 4 5
| String text = """
Lorem ipsum dolor sit amet, consectetur adipiscing \
elit, sed do eiusmod tempor incididunt ut labore \
et dolore magna aliqua.\
"""; |
Pattern Matching pour instanceof
En tant que développeur Java, vous avez probablement été dans une situation où vous devez vérifier si un objet est d'un certain type, et si c'est le cas le transtyper. Ce modèle est largement utilisé par exemple dans les implémentations equals. Java 14 introduit une fonctionnalité en préversion qui permet d'éliminer le besoin de transtypages explicites en passant par des vérifications instanceof. Par exemple, considérez le code suivant:
Code:
1 2 3 4 5 6
| if (obj instanceof Group) {
Group group = (Group) obj;
// use group specific methods
var entries = group.getEntries();
} |
Cet extrait peut être réécrit en utilisant la fonction en préversion comme ceci :
Code:
1 2 3
| if (obj instanceof Group group) {
var entries = group.getEntries();
} |
Étant donné que la vérification des conditions affirme que obj est de type Group, pourquoi devez-vous indiquer à nouveau que obj est de type Group avec le bloc de condition dans le premier extrait ? Ce besoin augmente potentiellement la possibilité d'erreurs.
La syntaxe plus courte supprimera de nombreux transtypages de programmes Java typiques.
« Il s'agit d'une fonctionnalité en préversion intéressante à expérimenter, car elle ouvre la porte à un pattern matching plus général. L'idée du pattern matching est de fournir une fonction de langage avec une syntaxe pratique pour extraire des composants d'objets en fonction de certaines conditions. C'est le cas avec l'opérateur instanceof, car la condition est une vérification de type et l'extraction appelle une méthode appropriée ou accède à un champ spécifique.
« En d'autres termes, cette fonctionnalité en préversion n'est que le début et vous pouvez vous attendre à une fonctionnalité de langage qui peut aider à réduire davantage la verbosité et ainsi réduire la probabilité de bogues ».
Les enregistrements
Il existe une autre fonctionnalité de langage en préversion : les enregistrements. Comme d'autres idées lancées jusqu'à présent, cette fonctionnalité suit la tendance de réduire la verbosité en Java et d'aider les développeurs à écrire du code plus concis. Les enregistrements se concentrent sur certaines classes de domaine dont le but est uniquement de stocker des données dans des champs et qui ne déclarent aucun comportement personnalisé.
Pour passer directement au problème, prenez une classe de domaine simple, BankTransaction, qui modélise une transaction avec trois champs: une date, un montant et une description. Vous devez vous soucier de plusieurs composants lorsque vous déclarez la classe :
- Le constructeur
- Les méthodes Getter
- toString()
- hashCode() et equals()
Le code de ces composants est souvent généré automatiquement par l'EDI et prend beaucoup de place. Voici une implémentation entièrement générée pour la classe BankTransaction:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| public class BankTransaction {
private final LocalDate date;
private final double amount;
private final String description;
public BankTransaction(final LocalDate date,
final double amount,
final String description) {
this.date = date;
this.amount = amount;
this.description = description;
}
public LocalDate date() {
return date;
}
public double amount() {
return amount;
}
public String description() {
return description;
}
@Override
public String toString() {
return "BankTransaction{" +
"date=" + date +
", amount=" + amount +
", description='" + description + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BankTransaction that = (BankTransaction) o;
return Double.compare(that.amount, amount) == 0 &&
date.equals(that.date) &&
description.equals(that.description);
}
@Override
public int hashCode() {
return Objects.hash(date, amount, description);
}
} |
Java 14 fournit un moyen de supprimer la verbosité et d'indiquer clairement que tout ce que vous voulez est une classe qui agrège uniquement les données avec les implémentations des méthodes equals, hashCode et toString. Vous pouvez réécrire BankTransaction comme suit:
Code:
1 2 3
| public record BankTransaction(Date date,
double amount,
String description) {} |
Avec un enregistrement, vous obtenez « automatiquement » les implémentations de equals, hashCode et toString en plus du constructeur et des Getters.
Les champs d'un enregistrement sont implicitement final. Cela signifie que vous ne pouvez pas les réaffecter. Notez, cependant, que cela ne signifie pas que l'ensemble de l'enregistrement est immuable; les objets eux-mêmes qui sont stockés dans les champs peuvent être mutables.
NullPointerExceptions
Considérez le code suivant :
Code:
var name = user.getLocation().getCity().getName();
Avant Java 14, vous pouvez obtenir l'erreur suivante:
Citation:
Envoyé par Message d'erreur
Exception in thread "main" java.lang.NullPointerException
at NullPointerExample.main(NullPointerExample.java:5)
Malheureusement, si à la ligne 5, il y a une affectation avec plusieurs invocations de méthode - getLocation() et getCity() - l'une ou l'autre pourrait retourner null. En fait, la variable user pourrait également être null. Par conséquent, la cause de <strong> NullPointerException </strong> n'est pas claire.
Maintenant, avec Java 14, il existe une nouvelle fonctionnalité JVM à travers laquelle vous pouvez recevoir des diagnostics plus informatifs:
Citation:
Envoyé par Message d'erreur
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Location.getCity()" because the return value of "User.getLocation()" is null
at NullPointerExample.main(NullPointerExample.java:5)
Le message comporte désormais deux éléments clairs:
- La conséquence: Location.getCity() ne peut pas être invoquée.
- La raison: la valeur de retour de User.getLocation() est nulle.
Source : Oracle
Du bon, du moins bon et des questions...
Blocs de texte
Citation:
Envoyé par
Stéphane le calme
Deux nouvelles séquences d'échappement ont été ajoutées dans Java 14. Premièrement, vous pouvez utiliser la nouvelle séquence d'échappement \s pour signifier un seul espace.
Sans un exemple, je ne vois pas trop l'intérêt par rapport à un espace tapé à la main
Citation:
Envoyé par
Stéphane le calme
Deuxièmement, vous pouvez utiliser une barre oblique inverse, \, comme moyen de supprimer l'insertion d'un nouveau caractère de ligne à la fin d'une ligne. Ceci est utile lorsque vous avez une très longue ligne que vous souhaitez diviser pour plus de lisibilité à l'intérieur d'un bloc de texte.
[...]
Avec la séquence d'échappement \ dans des blocs de texte, cela peut s'exprimer comme suit:
Code:
1 2 3 4 5
| String text = """
Lorem ipsum dolor sit amet, consectetur adipiscing \
elit, sed do eiusmod tempor incididunt ut labore \
et dolore magna aliqua.\
"""; |
Questions:
- Le retour à la ligne au début de la chaîne est-il obligatoire ou comptabilisé?
- Le \ enlève la fin de ligne mais les espaces au début ne sont-ils pas comptabilisés?
- Le choix de \ est discutable - certes, il existe dans d'autres langages mais ces derniers ont-ils d'autres séquences d'échappement commençant par \ ?
Que se passe-t-il si l'éditeur de texte rajoute un espace juste après? - Une meilleure syntaxe pour les chaînes très longues c'est très bien; mais quand aura-t-on droit à un soupçon d'interpolation? Parce que s'il faut écrire """très long""" + variable + """très long", les situations où on peut utiliser une chaîne très longue vont vite se réduire, au point qu'il sera plus efficace de mettre la chaîne dans un fichier séparé et de la lire comme une ressource!
Les enregistrements
Citation:
Envoyé par
Stéphane le calme
Avec un enregistrement, vous obtenez « automatiquement » les implémentations de equals, hashCode et toString en plus du constructeur et des Getters.
Oui mes les getters s'appellent-ils getDate(), date() ou simplement date (après tout comme la variable est finale, l'intérêt de la protéger est moindre)
Les enregistrements sont-ils des classes ou des structures sans héritage?
Citation:
Envoyé par
Stéphane le calme
Il existe une autre fonctionnalité de langage en préversion : les enregistrements. Comme d'autres idées lancées jusqu'à présent, cette fonctionnalité suit la tendance de réduire la verbosité en Java et d'aider les développeurs à écrire du code plus concis. Les enregistrements se concentrent sur certaines classes de domaine dont le but est uniquement de stocker des données dans des champs et qui ne déclarent aucun comportement personnalisé.
Cet article étant une traduction, il est un peu dommage que vous n'ayez pas inclus la traduction de cette partie:
Citation:
Stay tuned. Records also raise interesting questions from an educational standpoint for the next generation of Java developers. For example, if you mentor junior developers, when should records be introduced in the curriculum: before introducing OOP and classes or after?
Franchement, autant les autres fonctions sont utiles, autant celle-là, j'aimerais la voir disparaître. Elle ne va pas seulement "réduire la verbosité", elle va surtout conforter ceux qui travaillent toujours de la même façon à base soit de copier-coller soit de génération automatique (genre avec Eclipse, créer les champs et demander la génération automatique des accesseurs). Au final, les gens vont lire la spécification Java Beans et générer des POJO, c'est à dire des objets sans aucune intelligence où on se demande bien quelle est la valeur ajoutée des getters et des setters. Et toutes les méthodes un tant soit peu utiles vont se retrouver dans des "objets" séparés qui ne contiennent aucune donnée ou presque, genre les "data access objects". Soit exactement le contraire de ce qu'essaie de faire la programmation objet :aie::aie::aie: