Erfordert die Einführung der neuen Lambda-Notation (siehe z. B. diesen Artikel ) in Java 8 eine Art Typinferenz?
Wenn ja, wie wird sich das neue Typsystem auf die Java-Sprache insgesamt auswirken?
Erfordert die Einführung der neuen Lambda-Notation (siehe z. B. diesen Artikel ) in Java 8 eine Art Typinferenz?
Wenn ja, wie wird sich das neue Typsystem auf die Java-Sprache insgesamt auswirken?
Antworten:
In der Antwort von Ratschenfreak und in seinem Kommentarthread gibt es einiges an falschen Informationen . Ich werde hier in einer Antwort antworten, da ein Kommentar zu klein ist. Da dies eine Antwort ist, werde ich auch versuchen, die ursprüngliche Frage zu beantworten. (Beachten Sie jedoch, dass ich kein Experte für Typsysteme bin.)
Erstens lauten die kurzen Antworten auf die ursprüngliche Frage "Ja" und "Nein". Ja, Java 8 weist erheblich mehr Typunterschiede auf als Java 7, und Nein, es gibt kein "neues" Typsystem in Java 8, obwohl es einige geringfügige Änderungen gibt .
Java 8 wird weiterhin statisch typisiert sein und die Dichotomie zwischen Klassen und Schnittstellen beibehalten. Es gibt keine neuen Typen wie Funktionstypen. Der Typ eines Lambda ist im Wesentlichen eine "funktionale Schnittstelle", die eine gewöhnliche Schnittstelle mit einer einzelnen abstrakten Methode ist.
Schnittstellen können jetzt Code in Form von Standardmethoden haben, das Modell der einfachen Vererbung von Klassen und der mehrfachen Vererbung von Schnittstellen bleibt jedoch dasselbe. Natürlich gibt es einige Anpassungen, z. B. Regeln für die Methodenauflösung bei Vorhandensein von Standardmethoden, aber die Grundlagen bleiben unverändert.
Jeder Typ, der durch Typinferenz abgeleitet wird, kann explizit ausgeschrieben werden. Um das Beispiel eines Ratschenfreaks zu verwenden ,
Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });
ist im Grunde Zucker für
Collections.<MyClass>sort(list,
(Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));
So sparkleshy ‚s Aussage‚Typinferenz erfordert keine Erweiterung des Typsystems‘ist grundsätzlich richtig.
Um auf syntaktischen Zucker zurückzukommen, wiederhole ich meine Aussage, dass ein Lambda-Ausdruck für eine anonyme innere Klasse kein syntaktischer Zucker ist. Ratchet Freak erklärt , dass ein Lambda - Ausdruck in eine anonyme innere Klasse Instanziierung übersetzt wird, und Sparkleshy einfach bekräftigten , dass eine Lambda ist syntaktischer Zucker für eine anonyme innere Klasse, aber diese Aussagen sind falsch. Sie basieren wahrscheinlich auf veralteten Informationen. Frühe Lambda-Implementierungen haben Lambdas auf diese Weise implementiert, aber die Dinge haben sich geändert.
Lambda-Ausdrücke unterscheiden sich semantisch von inneren Klassen und werden anders als innere Klassen implementiert.
Lambda-Ausdrücke unterscheiden sich semantisch in einigen Punkten von inneren Klassen. Bei der Auswertung eines Lambda-Ausdrucks muss nicht jedes Mal eine neue Instanz erstellt werden. Sie haben auch unterschiedliche Erfassungssemantiken, zum Beispiel erfassen sie diese unterschiedlich. In einer inneren Klasse, dies ist die innere Klasseninstanz, wohingegen in einer Lambda, dies ist die umgebende Instanz. Folgendes berücksichtigen:
public class CaptureThis {
void a(Runnable r) { r.run(); }
void b() {
a(new Runnable() { public void run() { System.out.println(this); }});
a(() -> System.out.println(this));
}
public String toString() { return "outer"; }
public static void main(String[] args) { new CaptureThis().b(); }
}
In einem aktuellen Lambda-Build für JDK 8 (ich habe b69 verwendet ) sieht die Ausgabe ungefähr so aus:
CaptureThis$1@113de03
outer
Darüber hinaus werden Lambda-Ausdrücke ganz anders als innere Klassen implementiert. Wenn Sie die disassemblierte Ausgabe vergleichen, werden Sie feststellen, dass der Code der inneren Klasse direkt zur Erstellung kompiliert und zu einem Konstruktor von CaptureThis $ 1 aufgerufen wird, wohingegen der Lambda-Ausdruck zu einer aufgerufenen dynamischen Anweisung kompiliert wird, die eine nicht spezifizierte Runnable through-Anweisung liefert. Eine vollständige Erklärung der Funktionsweise und des Grunds finden Sie in Brian Goetz 'JavaOne 2012-Vortrag Lambda: Ein Blick unter die Haube .
this
mitMyClass.this