Java 10 LocalVariable Type-Inference

Java 10 Local Variable Type-Inference

1. Überblick

Eine der sichtbarsten Verbesserungen in JDK 10 ist die Typinferenz lokaler Variablen mit Initialisierern.

In diesem Lernprogramm werden die Details dieser Funktion anhand von Beispielen erläutert.

2. Einführung

Bis Java 9 mussten wir den Typ der lokalen Variablen explizit erwähnen und sicherstellen, dass er mit dem zur Initialisierung verwendeten Initialisierer kompatibel war:

String message = "Good bye, Java 9";

In Java 10 könnten wir folgendermaßen eine lokale Variable deklarieren:

@Test
public void whenVarInitWithString_thenGetStringTypeVar() {
    var message = "Hello, Java 10";
    assertTrue(message instanceof String);
}

Wir geben nicht den Datentypmessage an. Stattdessen markieren wirthe message as avar, und der Compiler leitet den Typmessage  vom Typ des auf der rechten Seite vorhandenen Initialisierers ab.

Im obigen Beispiel wäre der Typ vonmessage String.

Note that this feature is available only for local variables with the initializer. Es kann nicht für Elementvariablen, Methodenparameter, Rückgabetypen usw. verwendet werden. Der Initialisierer ist erforderlich, da der Compiler den Typ nicht ableiten kann.

Diese Verbesserung trägt dazu bei, den Code des Boilerplates zu reduzieren. zum Beispiel:

Map map = new HashMap<>();

Dies kann nun umgeschrieben werden als:

var idToNameMap = new HashMap();

Dies hilft auch, sich auf den Variablennamen und nicht auf den Variablentyp zu konzentrieren.

Eine andere zu beachtende Sache ist, dassvar is not a keyword - dies stellt die Abwärtskompatibilität für Programme sicher, dievar say als Funktions- oder Variablennamen verwenden. var ist ein reservierter Typname, genau wieint.

Beachten Sie schließlich, dassno runtime overhead in using var nor does it make Java a dynamically typed language.  vorhanden ist. Der Typ der Variablen wird zum Zeitpunkt der Kompilierung noch abgeleitet und kann später nicht mehr geändert werden.

3. Illegale Verwendung vonvar

Wie bereits erwähnt, funktioniertvar ohne den Initialisierer nicht:

var n; // error: cannot use 'var' on variable without initializer

Es würde auch nicht funktionieren, wenn es mitnull initialisiert würde:

var emptyList = null; // error: variable initializer is 'null'

Bei nicht lokalen Variablen funktioniert dies nicht:

public var = "hello"; // error: 'var' is not allowed here

Der Lambda-Ausdruck benötigt einen expliziten Zieltyp, und daher kannvar nicht verwendet werden:

var p = (String s) -> s.length() > 10; // error: lambda expression needs an explicit target-type

Gleiches gilt für den Array-Initialisierer:

var arr = { 1, 2, 3 }; // error: array initializer needs an explicit target-type

4. Richtlinien für die Verwendung vonvar

Es gibt Situationen, in denenvar can legal verwendet werden kann, dies ist jedoch möglicherweise keine gute Idee.

Zum Beispiel in Situationen, in denen der Code möglicherweise weniger lesbar ist:

var result = obj.prcoess();

Obwohl hier eine legale Verwendung vonvar ist, wird es schwierig, den Typ zu verstehen, der vonprocess()zurückgegeben wird, wodurch der Code weniger lesbar wird.

java.netenthält einen speziellen Artikel zuStyle Guidelines for Local Variable Type Inference in Java , in dem erläutert wird, wie wir bei Verwendung dieser Funktion ein Urteil fällen sollten.

Eine andere Situation, in der es am besten ist,var is in Streams mit langer Pipeline zu vermeiden:

var x = emp.getProjects.stream()
  .findFirst()
  .map(String::length)
  .orElse(0);

Die Verwendung vonvar may führt ebenfalls zu einem unerwarteten Ergebnis.

Wenn wir es beispielsweise mit dem in Java 7 eingeführten Diamantoperator verwenden:

var empList = new ArrayList<>();

Die Art vonempLististArrayList<Object>and, nichtList<Object>. Wenn wir wollen, dass esArrayList<Employee> ist, müssen wir explizit sein:

var empList = new ArrayList();

Die Verwendung vonvar mit nicht denotierbaren Typen kann zu unerwarteten Fehlern führen.

Wenn wir zum Beispielvar mit der anonymen Klasseninstanz verwenden:

@Test
public void whenVarInitWithAnonymous_thenGetAnonymousType() {
    var obj = new Object() {};
    assertFalse(obj.getClass().equals(Object.class));
}

Wenn wir nun versuchen, weitereObjecttoobj zuzuweisen, erhalten wir einen Kompilierungsfehler:

obj = new Object(); // error: Object cannot be converted to 

Dies liegt daran, dass der abgeleitete Typ vonobj nichtObject ist.

5. Fazit

In diesem Artikel wurde die neue Inferenzfunktion für lokale Variablen in Java 10 anhand von Beispielen vorgestellt.

Wie üblich können Codefragmenteover on GitHub gefunden werden.