Verallgemeinerte Zieltypinferenz in Java

Generalized Target-Type Inference in Java

1. Einführung

Type Inference wurde in Java 5 als Ergänzung zur Einführung von Generika eingeführt und in den folgenden Java-Versionen, die auch als Generalized Target-Type Inference bezeichnet werden, erheblich erweitert.

In diesem Tutorial werden wir dieses Konzept anhand von Codebeispielen untersuchen.

2. Generika

Generika haben uns viele Vorteile gebracht, z. B. eine erhöhte Schriftsicherheit, die Vermeidung von Fehlern bei der Typumwandlung und generische Algorithmen. Weitere Informationen zu Generika finden Sie inarticle.

Die Einführung vongenerics resulted in the necessity of writing boilerplate code due to the need to pass type parameters. Einige Beispiele sind:

Map> mapOfMaps = new HashMap>();
List strList = Collections.emptyList();
List intList = Collections.emptyList();

3. Typinferenz vor Java 8

Um die unnötige Code-Ausführlichkeit zu reduzieren, wurde Type Inference in Java eingeführt, is the process of automatically deducing unspecified data types of an expression based on the contextual information.

Jetzt können wir dieselben generischen Typen und Methoden aufrufen, ohne die Parametertypen anzugeben. Der Compiler fügt die Parametertypen bei Bedarf automatisch ein.

Mit dem neuen Konzept können wir denselben Code sehen:

List strListInferred = Collections.emptyList();
List intListInferred = Collections.emptyList();

Im obigen Beispiel kann der Compiler basierend auf den erwarteten RückgabetypenList<String> undList<Integer> den Typparameter auf die folgende generische Methode ableiten:

public static final  List emptyList()

Wie wir sehen können, ist der resultierende Code kurz. Now, we can call generic methods as an ordinary method if the type parameter can be inferred.

In Java 5 können wir die Typinferenz in bestimmten Kontexten durchführen, wie oben gezeigt.

Java 7 erweiterte die Kontexte, in denen es ausgeführt werden konnte. Es wurde der Diamantoperator<> eingeführt. Weitere Informationen zum Diamantoperator finden Sie inarticle.

Nun istwe can perform this operation for generic class constructors in an assignment context. ein solches Beispiel:

Map> mapOfMapsInferred = new HashMap<>();

Hier verwendet der Java-Compiler den erwarteten Zuweisungstyp, um die Typparameter auf den Konstruktor vonHashMapabzuleiten.

4. Generalized Target-Type Inference - Java 8

Mit Java 8 wurde der Umfang von Type Inference weiter erweitert. Wir bezeichnen diese erweiterte Inferenzfunktion als Generalized Target-Type Inference. Sie können die technischen Detailshere lesen.

Java 8 führte auch Lambda Expressions ein. Lambda Expressions do not have an explicit type.  Their type is inferred by looking at the target type of the context or situation. Der Zieltyp eines Ausdrucks ist der Datentyp, den der Java-Compiler erwartet, je nachdem, wo der Ausdruck angezeigt wird.

Java 8 unterstützt die Inferenz mit Target-Type in einem Methodenkontext. When we invoke a generic method without explicit type arguments, the compiler can look at the method invocation and corresponding method declarations to determine the type argument (or arguments) that make the invocation applicable.

Sehen wir uns einen Beispielcode an:

static  List add(List list, T a, T b) {
    list.add(a);
    list.add(b);
    return list;
}

List strListGeneralized = add(new ArrayList<>(), "abc", "def");
List intListGeneralized = add(new ArrayList<>(), 1, 2);
List numListGeneralized = add(new ArrayList<>(), 1, 2.0);

Im Code gibtArrayList<> das Typargument nicht explizit an. Also muss der Compiler darauf schließen. Zunächst untersucht der Compiler die Argumente der add-Methode. Anschließend werden die Parameter untersucht, die bei verschiedenen Aufrufen übergeben wurden.

It performs invocation applicability inference analysis to determine whether the method applies to these invocations. Wenn aufgrund von Überladung mehrere Methoden anwendbar sind, würde der Compiler die spezifischste Methode auswählen.

Dannthe compiler performs invocation type inference analysis to determine the type arguments.The expected target types are also used in this analysis. Die Argumente in den drei Instanzen werden alsArrayList<String>,ArrayList<Integer> undArrayList<Number> abgeleitet.

Target-Type-Inferenz ermöglicht es uns, keine Typen für Lambda-Ausdrucksparameter anzugeben:

List intList = Arrays.asList(5, 2, 4, 2, 1);
Collections.sort(intList, (a, b) -> a.compareTo(b));

List strList = Arrays.asList("Red", "Blue", "Green");
Collections.sort(strList, (a, b) -> a.compareTo(b));

Hier haben die Parametera undb keine explizit definierten Typen. Ihre Typen werden im ersten Lambda-Ausdruck alsInteger und im zweiten alsString abgeleitet.

5. Fazit

In diesem kurzen Artikel haben wir Type Inference besprochen, mit dem wir zusammen mit Generika und Lambda Expression prägnanten Java-Code schreiben können.

Wie üblich kann der vollständige Quellcodeover on Github gefunden werden.