Modifications de la syntaxe Java envisagées par Amber

Qu'est-ce que l'ambre

Un projet pour étendre le langage Java http://openjdk.java.net/projects/amber/

Branche d'Ambre

http://hg.openjdk.java.net/amber/amber/branches

Je pense que cela sera publié lors de la cérémonie de la pluie de mai tous les six mois avec JDK14, 15, 16 ... C'est assez effrayant.

Records[preview in JDK14] C'est une classe pour contenir des données. JEP est ici en avant-première en 14. JEP 359: Records (Preview) Le flux de l'aperçu 2 en Java 15 et de la formalisation en Java 16.

~~ JEP n'est pas trouvé pour l'instant. ~~ ~~ Cliquez ici pour le brouillon JEP ~~ ~~JEP draft: Records and Sealed Types~~

http://cr.openjdk.java.net/~briangoetz/amber/datum.html http://hg.openjdk.java.net/amber/amber/file/15a61b5af8f5/test/langtools/tools/javac/datum

Définissez-le comme enregistrement.

record Foo(int x, int y) {}

Les autres classes ne peuvent pas être héritées.

record Nom de l'enregistrement(Statut) {Définition}

Ce serait une classe comme celle-ci:

class Foo extends Record{
  //État défini comme final privé
  private final int x;
  private final int y;
  //Aucun champ d'instance supplémentaire ne peut être défini

  //Un constructeur qui définit l'état du champ est défini
  public Foo(int x, int y) {
    this.x = x;
    this.y = y;
  }

  //Une méthode portant le même nom que l'état est définie
  public int x() {
    return x;
  }
  public int y() {
    return y;
  }

  //Un hashCode qui reflète l'état est défini
  public int hashCode() { ... }
  //Les états égaux à comparer sont définis
  public boolean equals() { ... }
  //Un toString qui affiche l'état est défini
  public String toString() { ... }
}

Vous pouvez définir un constructeur pour la vérification d'état et la normalisation.

record Range(int lo, int hi) {
  public Range {
    if (lo > hi) throw IllegalArgumentException();
    //Les champs qui n'ont pas été définis seront définis ultérieurement
  }
}

Des améliorations dans l'aperçu 2 sont suggérées ici. https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001913.html

--java.util.Record est une classe, mais la classe en ligne de Valhalla ne peut hériter que de l'interface, alors devrait-il s'agir d'une interface?

type scellé

Un type scellé qui limite l'héritage est également promu. JEP 360: Sealed Types (Preview) Les spécifications de type scellé sont également décidées comme un ensemble avec un enregistrement ~~. ~~ ~~JEP draft: Records and Sealed Types~~ Il semble être en avant-première avec JDK15.

Vous pouvez limiter l'héritage. Pour la correspondance de motifs

sealed interface Node 
  permits A, B, C {}

Node est implémenté dans les classes A, B et C spécifiées dans permit. Vous pouvez omettre les «permis» s'ils sont dans la même unité de compilation. Les interfaces et les classes abstraites qui héritent du type scellé sont des types scellés. La classe non abstraite qui implémente et hérite du type scellé est finale.

sealed interface Expr {};

record AddExpr(Expr a, Expr b) implements Expr {}
record SubExpr(Expr a, Expr b) implements Expr {}
record MulExpr(Expr a, Expr b) implements Expr {}
record DivExpr(Expr a, Expr b) implements Expr {}

Il est également intéressant d'inclure le mot-clé séparé par des tirets «non scellé».

Correspondance de modèle [aperçu dans JDK 14]

C'est une correspondance de modèle. Tout d'abord, une correspondance de motif utilisant l'instance de sera incluse dans 14 en tant qu'aperçu. http://openjdk.java.net/jeps/305

Vous pouvez faire correspondre les valeurs avec la valeur instanceof pattern. Le modèle est une définition constante ou variable. Dans le cas d'une définition de variable, si les types correspondent, cela devient vrai et une valeur est affectée à cette variable.

if (x instanceof Integer i) {
    // can use i here
}

Ce sera 15 ou plus tard, mais la correspondance de modèle peut également être utilisée avec le commutateur. JEP draft: Pattern matching for switch (Preview)

String formatted;
switch (obj) {
    case Integer i: formatted = String.format("int %d", i); break;
    case Byte b:    formatted = String.format("byte %d", b); break;
    case Long l:    formatted = String.format("long %d", l); break;
    case Double d:  formatted = String.format("double %f", d); break;
    case String s:  formatted = String.format("String %s", s); break
    default:        formatted = obj.toString();
}

Ce n'est pas encore JEP, mais l'objectif est de pouvoir effectuer une décomposition structurelle en combinaison avec des classes de données.

record Point(int x, int y) {}

int getLen(Point p) {
  return switch (p) {
    case Point(0, int y) -> y;
    case Point(int x, 0) -> x;
    case Point(int x, int y) -> (int)sqrt(x * x + y * y);
  }
}

Ensuite, vous pourrez peut-être utiliser double et booléen avec le commutateur.

switch (obj) {
  case 12 :   msg = "12"; break;
  case true : msg = "Turu"; break;
  case 3.14:  msg = "Dans le rapport de circonférence"; break;
}

Commutateur étendu [standard dans JDK 14, aperçu dans JDK 12, 13]

Vous pouvez maintenant utiliser l'instruction précédente switch comme expression. Il semble qu'il sera introduit en tant qu'aperçu dans Java 12, un changement de spécification dans Java 13 et une fonction officielle dans Java 14. https://openjdk.java.net/jeps/361

Aperçu JEP https://openjdk.java.net/jeps/325 https://openjdk.java.net/jeps/354

Switch était une instruction, mais comme de nombreux commutateurs l'utilisaient pour affecter des valeurs à la même variable ou renvoyer dans tous les cas, il peut également être utilisé comme une expression afin de pouvoir être écrit efficacement. Je vais.

En d'autres termes, comme ça.

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

Vous pouvez également renvoyer une valeur avec yield.

int result = switch (s) {
    case "Foo":
        yield 1;
    case "Bar":
        yield 2;
    default:
        System.out.println("Neither Foo nor Bar, hmmm...");
        yield 3;
}

La forme de base consiste à renvoyer une valeur avec «yield».

case LABEL: yield expression;

Il semble que vous puissiez écrire comme lambda comme sucre de syntaxe.

case LABEL -> expression;

Il vous permet également de spécifier plusieurs valeurs pour «case».

switch (day) {
    case MONDAY, FRIDAY, SUNDAY: 
        numLetters = 6;
        break;
    ...
};

Ces extensions «case» sont également valides pour les instructions «switch» existantes.

J'aurais dû pouvoir utiliser "null" pour "case", mais il semble que ce soit hors de JEP325.

String formatted = switch (s) {
    case null -> "(null)";
    case "" -> "(empty)";
    default -> s;
}

S'il n'y a pas de "case null", la "case" suivante est automatiquement insérée.

case null: throw new NullPointerException();

Extension du littéral de chaîne [aperçu dans JDK 13,14]

http://openjdk.java.net/jeps/368

Vous pouvez définir une chaîne de caractères comprenant des sauts de ligne. Insérez dans "" "" `. Il est inclus en tant qu'aperçu dans JDK13. http://openjdk.java.net/jeps/355

Dans JDK14, il y a quelques changements de spécification tels que les sauts de ligne d'échappement. Il sera standard dans JDK15.

Au départ, je prévoyais d'entrer JDK 12 en tant que littéraux de chaîne bruts, mais il a été rejeté. ~~http://openjdk.java.net/jeps/326~~

// same as "You can write\ntwo line string.\n"
var str = """
  You can write
  two line string.
  """;

Le début "" "" "ne peut pas être suivi d'une chaîne, et le retrait est basé sur le" "" "ou la partie la moins profonde de la chaîne interne.

var str = """
..You can write
..two line string.
  """;
var str = """
..  You can write
..  two line string.
  """;

Vous pouvez également échapper aux sauts de ligne.

var str = """
  You can write \
  two line string, \
  but this is single.
  """;

Ce sera "" Vous pouvez écrire une chaîne de deux lignes, mais celle-ci est unique. "`.

L'espace à la fin de la ligne est supprimé. Donc, si vous avez besoin d'un espace à la fin de la ligne, mettez \ s pour indiquer que vous avez besoin d'un espace.

var str = """
  test\s
  test \s
  """;

Ce sera "" test_ \ ntest__ \ n "`. (Dans Qiita, même si vous mettez plusieurs espaces, ce sera un espace)

Ce n'est pas grave, mais Qiita```Je pense qu'il y aura beaucoup de gens en difficulté parce que les citations arrière ne peuvent pas être entourées par les citations arrière. 2018/5/À partir de 8, il est rendu comme suit. Capture d'écran 2018-05-08 4.38.25.png

#Correction mineure Lambda Correction mineure Lambda http://openjdk.java.net/jeps/302

Pour les variables inutilisées_Peut être utilisé.

BiFunction<Integer, String, String> biss = (i, _) -> String.valueOf(i);

Aussi, dans les cas suivantsfalseParce qu'il revientPredicateIl est clair que ce sera le cas, mais pour le moment, c'est une erreur. L'idée est de pouvoir taper correctement l'inférence.

m(Predicate<String> ps) { ... }
m(Function<String, String> fss) { ... }

m(s -> false) //ambiguous

#Énumération étendue L'idée est de permettre à enum de spécifier des génériques. http://openjdk.java.net/jeps/301

enum Argument<X> { // declares generic enum
   STRING<String>(String.class), 
   INTEGER<Integer>(Integer.class), ... ;

   Class<X> clazz;

   Argument(Class<X> clazz) { this.clazz = clazz; }

   Class<X> getClazz() { return clazz; }
}

Class<String> cs = Argument.STRING.getClazz(); //uses sharper typing of enum constant

#Définition de méthode simplifiée

http://openjdk.java.net/jeps/8209434

Dans la définition de la méthode->Pour pouvoir utiliser

int twice(int x) -> x * x;

La référence de la méthode est=alors

int min(int x, int y) = Integer::min;

Les transferts tels que la surcharge et le remplacement peuvent être écrits proprement.

#Méthode locale

2019/11/Depuis 16, il n'y a pas de JEP etc., mais si vous regardez la branche du référentiel orange, il y a un signe que vous faites une extension qui vous permet de définir des méthodes dans les méthodes.

Il vous permet de définir les méthodes dans la méthode comme suit:

int norm(int x, int y) {
  int square(int n) {
    return n * n;
  }
  return square(x) + square(y);
}

Combiné à la simplification de la définition de la méthode, vous devriez être capable d'écrire:

int norm(int x, int y) {
  int square(int n) -> n * n;
  return square(x) + square(y);
}

#Inférence de type de variable locale[standard in JDK10] Il introduit l'inférence de type pour les variables locales. http://openjdk.java.net/jeps/286

var x = 12;

Introduit dans JDK 10.

#Var support pour lambda[standard in JDK11] Aussi dans la définition variable de lambdavarEst destiné à pouvoir être écrit explicitement. http://openjdk.java.net/jeps/323

J'écrivais comme ça.

(x, y) -> x + y

varEst une tentative de spécifier explicitement qu'il s'agit d'une inférence de type.

(var x, var y) -> x + y

Ne peut pas être mélangé

(var x, y) -> x + y

Entré JDK 11.

#Autre que la syntaxe Il semble qu'une version constructeur d'indy soit en cours de développement sous le nom de condy. ->C'était une dynamique constante. http://openjdk.java.net/jeps/309

Entré JDK 11.

Recommended Posts

Modifications de la syntaxe Java envisagées par Amber
Syntaxe de contrôle Java
Syntaxe de contrôle Java
Changements dans Java 11
Changements de Java 8 à Java 11
[Java] Note sur la syntaxe de contrôle
[Pour les débutants] À propos de la syntaxe JavaScript expliquée par Java Gold