Ich habe eine Methode mit type-Argumenten erstellt, die einen generischen Typ mit diesen type-Argumenten zurückgibt und Function
arguments verwendet, was auch von den type-Argumenten abhängt. Wenn ich lambdas als Argumente verwende, zwingt mich der Compiler, die Typargumente der Methode anzugeben, die sich falsch anfühlt.
Ich entwerfe eine Dienstprogrammklasse mit Methoden, die mit Stream.flatMap
verwendet werden können. Er ordnet alle Arten von Auflistungseinträgen einem FlatEntry zu, das ein Schlüssel- und Wertelement enthält, und kann dies auf mehreren Ebenen mit einem Builder tun. Die betroffene Methode ist flatEntryMapperBuilder
. Hier ist der Code:
Das Problem kommt mit seiner Verwendung. Sprich ich habe:
%Vor%Ich kann jedes Element in den Untergruppen einem FlatEntry zuordnen, indem ich Folgendes tue:
%Vor%Und es funktioniert gut. Aber wenn ich das versuche:
%Vor%Der Eclipse (Mars 4.5.0) Compiler bricht mit:
%Vor%Und javac (1.8.0_51) bricht mit:
%Vor% Wenn ich Entry::getKey
durch entry -> entry.getKey()
ersetze, ändert javac seine Ausgabe drastisch:
Es kompiliert durch Angabe von Typparametern, was ich erwartet habe:
%Vor%oder einen der Argumente type Parameter angeben:
%Vor%Aber das ist tollpatschig! Stellen Sie sich jetzt vor, wie ungeschickt es wäre, alle Typparameter mit 2 Ebenen in der Karte zu schreiben, mit der Kettenmethode (was meine Zielverwendung ist):
%Vor%Ich habe viele andere Fragen über lambdas und Generika gelesen, aber keiner beantwortet meinen speziellen Fall.
Vermisse ich etwas? Kann ich meine API so korrigieren, dass ihre Verwendung weniger schwerfällig ist, oder muss ich immer nur Typargumente angeben? Danke!
Holger hatte meiner Meinung nach die beste Antwort im Kommentarbereich:
Dies ist eine bekannte Einschränkung der Typ-Inferenz von Java 8. Es funktioniert nicht mit verketteten Methodenaufrufen wie
genericFactoryMethod().build()
.
Danke! Über meine API werde ich die Funktionen spezifizieren, bevor ich sie als Argumente benutze:
%Vor%EDIT: Ich habe die API dank Holgers Kommentaren überarbeitet (danke nochmal!). Es behält das ursprüngliche Element anstelle eines Schlüssels zusammen mit dem abgeflachten Wert bei.
%Vor% Es ist verkettbar, ab Level 2 muss der Mapper ein FlatEntry
verarbeiten. Die Verwendung ähnelt einem einfachen flatMap
:
Eine Möglichkeit, dem Compiler genügend Typinformationen zur Verfügung zu stellen, besteht darin, einen expliziten Typ eines der Lambda-Argumente anzugeben. Dies ist in demselben Sinne wie Ihre Antwort , aber etwas kompakter, da Sie nur den Typ des Arguments und nicht die ganze Funktion angeben müssen.
Das sieht für die einstufige Karte ziemlich gut aus:
%Vor%Die zweistufige Karte ist jedoch an der Grenze zum Grotesken:
%Vor%Tags und Links java java-8 lambda generics type-inference