Wie wird die neue Entwicklung von Java die Interoperabilität mit Sprachen wie Scala und Clojure beeinflussen?

11

Soweit ich weiß, wurden sowohl Scala als auch Clojure als neue Sprachen konzipiert

  1. abhängig von der JVM und
  2. Einfache Integration in Java-Code in dem Sinne, dass Java-Klassen in Scala- und Clojure-Code verwendet werden können.

Ab Java 8 (und möglicherweise noch stärker mit nachfolgenden Versionen von Java) wird sich die Semantik der Java-Sprache ändern.

Ich wollte fragen, wie sich diese Änderungen auf die Interoperabilität zwischen Java und Scala / Clojure auswirken und welche Konsequenzen dies haben wird. Da Lambdas in Java 8 beispielsweise keine Objekte sind (siehe z. B. hier ), müssen sich Scala und Clojure möglicherweise mit Java-Werten befassen, die keine Objekte sind. Wäre das ein Problem?

Ich kann mir folgende Szenarien vorstellen:

  1. Die Scala- oder Clojure-Sprache wird erweitert, um sich an die neue Java-Semantik anzupassen (um die neuen Nicht-Objektwerte zu verarbeiten) und die Interoperabilität mit Java zu unterstützen.
  2. Die Scala- oder Clojure-Sprache wird nicht erweitert. Dies wäre nur möglich, wenn die neuen Java-Funktionen wie Funktionswerte vorhandenen Konzepten zugeordnet werden können. In Scala ist beispielsweise sogar eine Funktion ein Objekt. Ich denke, Java-Funktionen würden wieder in eine Art Objekt eingeschlossen, wenn sie für Scala sichtbar werden.
  3. Die Scala- oder Clojure-Sprache unterstützt weiterhin die Interoperabilität bis Java 6 oder 7, ohne die neueste Java-Entwicklung zu verfolgen. Dies würde erfordern, dass ältere Versionen von Java weiterhin unterstützt werden (zumindest von OpenJDK oder einem anderen Projekt), damit diese Sprachen auf einem konservativeren / stabileren Zweig von Java basieren können.

Zusammenfassend: Können wir erwarten, dass sich die zukünftige Entwicklung von Java auf Sprachen wie Scala und Clojure auswirkt, um die Interoperabilität mit Java aufrechtzuerhalten? Gibt es bereits eine (Link zu) laufende Diskussion zu diesem Thema?

Hinweis

Ich kann mir vorstellen, dass Scala, Clojure und andere JVM-basierte Sprachen keine größeren Probleme haben werden, ihre Implementierung auf neuere Versionen der JVM zu aktualisieren (und dass neue JVM-Funktionen diese Implementierung noch einfacher machen werden). Meine Frage konzentriert sich auf Funktionen von Java als Sprache und darauf, ob / wie andere JVM-Sprachen diese neuen Funktionen "sehen" / verwenden können, und nicht darauf, ob JVM-basierte Sprachen auf den neuesten JVMs ausgeführt werden.

Giorgio
quelle
6
Es ist ungenau zu sagen, dass Scala usw. von Java abhängen. Sie hängen vom JVM-Bytecode ab. Alle Interoperabilitätsfunktionen beziehen sich auf Bytecode und nicht auf den Quellcode der Java-Sprache. Daher sind alle Änderungen, die an Java selbst vorgenommen werden, keine Bedrohung. Nur Änderungen an der JVM können sich auf diese Sprachen auswirken, und die JVM ist äußerst konservativ - sie entfernt im Grunde nie die Unterstützung für irgendetwas. Tatsächlich sind die meisten Änderungen in der JVM heutzutage speziell für die neueren dynamischen Sprachen vorgesehen.
Kilian Foth
@ Kilian Foth: Soweit ich weiß, ist eine Scala Stringein Java String. Daher verwendet Scala bestimmte Java-Bibliotheksklassen. Aber ich kann die Formulierung ändern, wenn Sie denken, dass sie zu stark ist.
Giorgio
@ Kilian Foth: Ich habe den Begriff abhängig entfernt, da der Schwerpunkt meiner Frage eher auf der Interoperabilität zwischen Scala und Java liegt. Clojure und Java.
Giorgio
@KilianFoth Dies sollte eine Antwort sein, da es das Hauptanliegen der Frage anspricht. Das Hauptziel jeder neuen Java-Version ist die Abwärtskompatibilität.
maple_shaft
3
@maple_shaft: Ich habe meine Frage korrigiert und das Wort "abhängig" entfernt. Wie ich in einem anderen Kommentar ausgeführt habe, geht es mir nicht darum, wie Scala oder Clojure von Java- oder JVM-Funktionen abhängen, sondern wie Scala / Clojure Java-Funktionen "sehen" kann. Soweit ich weiß, können sie Java 6-Funktionen wie Klassen, Schnittstellen, Objekte, Methoden und primitive Datentypen sehen. Dadurch kann Scala / Clojure Java 6-Code verwenden (aufrufen). Meine Frage ist, ob diese Sprachen auch zukünftige Java-Sprachkonstrukte "sehen" (und daher verwenden können) oder ob dies Erweiterungen der Scala / Clojure-Sprachen erfordert.
Giorgio

Antworten:

15

Tatsächlich führt Java 8 nicht viel ein, was sich nachteilig auf andere JVM-Sprachen auswirkt, die mit Java zusammenarbeiten. Die Arbeit an Lambdas hat dazu beigetragen, eine Reihe kleiner Probleme im Zusammenhang mit invokedynamic, MethodHandles, MethodReferences usw. zu beheben - aber ansonsten geht es normal weiter. Das heißt, es gibt eine ganze Reihe neuer APIs, auf die die anderen JVM-Sprachen möglicherweise jetzt zugreifen könnten. Welche sie standardmäßig verwenden oder nicht, liegt bei ihnen.

Die größte Änderung, die sich auf Interop auswirkt, kam tatsächlich mit Java 7 - mit dem aufgerufenen dynamischen Bytecode, der dynamische / späte Bindungsaufrufe innerhalb der JVM ermöglicht - etwas, das ursprünglich für die anderen Sprachen in der JVM entwickelt wurde. Es wurde seitdem sehr nützlich für Lamdbas angepasst, sodass Java ab Java 8 tatsächlich diese Bytecodes ausgibt.

Einige Sprachen (z. B. JRuby) verwenden bereits stark invokedynamic, während andere (Scala, Groovy et al.) Die Verwendung noch untersuchen oder sich in einem frühen Stadium des Patchen befinden. Theoretisch sind ihre dynamischen Aufrufe fast so performant wie vorhanden Java invokestatische Aufrufe im Gegensatz zu den unzähligen langsameren Problemumgehungen, die sie in der Vergangenheit verwenden mussten.

Java 9 wird JVM-Sprachen vor weitere Herausforderungen stellen, da das Projekt Jigsaw auf die Plattform kommt, das der Anfang vom Ende für das traditionelle Laden von Klassen und Klassenpfade für die JVM sein wird. Die Leute in der JVM-Sprache sind sich dessen ziemlich bewusst und ich erwarte eine vernünftige Zusammenarbeit.

Martijn Verburg
quelle
1
Aber soweit ich weiß, ist ein Scala-Verschluss ein Objekt.
Giorgio
1
Ja. Scala hat die Unterstützung für Java 1.5 erst kürzlich eingestellt. Es wird lange dauern, bis 1.6 eingestellt wird.
Jörg W Mittag
1
@Giorgio Die Sprachfunktionen von Java spielen keine Rolle, da die meisten davon beim Kompilieren mit Bytecode-Tricks gleichgesetzt werden. Wenn wir akzeptieren, dass die JVM immer abwärtskompatibel ist, auch wenn neue Bytecodes eingeführt werden, bleibt Scala davon unberührt und kann diese neuen JVM-Funktionen nach Belieben nutzen.
maple_shaft
1
"Die Sprachfunktionen von Java spielen keine Rolle, da die meisten von ihnen beim Kompilieren ohnehin Bytecode-Tricks entsprechen.": Wenn eine andere Sprache ein Java-Konstrukt verwenden möchte, muss sie den für dieses Konstrukt generierten Bytecode erkennen können. Wenn Java ein neues Konstrukt einführt, das einem neuen Bytecode zugeordnet ist, sollte die Hostsprache mindestens einen neuen Wrapper / eine neue Schnittstelle implementieren, um den neuen Bytecode zu erkennen und zu verwenden. Wenn beispielsweise ein Java 8-Lambda kein Objekt, sondern ein neues Konstrukt mit neuem, spezifischem Bytecode erstellt hat, muss die Hostsprache angepasst werden, um es zu erkennen.
Giorgio
2
@Giorgio: Sicher, aber für die Java 8-Plattform sind keine derartigen Änderungen geplant. Tatsächlich wurde das JVMS in der gesamten Geschichte der Java-Plattform in den Jahren 2003 und 2010 nur zweimal erweitert , und das zweite Mal (Einführung des invokedynamicBytecodes) wurde speziell zur Unterstützung anderer Sprachen als Java verwendet. in der Tat, die Java 7 Sprache nicht unterstützt oder dass Bytecode verwenden.
Jörg W Mittag
2

Scala wird gleich zurückgelassen, wenn Java Lambdas hinzufügt, da Java-Lambdas einen Typ entsprechend dem Kontext zugewiesen bekommen, in dem sie verwendet werden, während Scala-Lambdas einen Typ zugewiesen bekommen, der auf ihren Aritäten, Parametertypen und Rückgabetypen basiert, z.

executor.execute(() -> { System.out.println("hello world"); });

aus Java 8 kann in Scala geschrieben werden als:

executor execute new Runnable {
    override def run() { println("hello world") }
}

es sei denn, Sie verwenden / schreiben einige Wrapper, die Scalas () => Unit in Runnable konvertieren.

Ricky Clarkson
quelle
Vielen Dank für die Antwort und auch für die Beantwortung meiner Frage (+1). Wenn ich das richtig verstehe, muss Scala weiterhin anonyme Klassen verwenden, um Schnittstellen in einem Kontext zu instanziieren, in dem Java 8 Lambdas verwendet (da Java 8-Lambdas eine andere Semantik als Scala-Lambdas haben). Ein weiterer Punkt, der mir nicht klar ist, ist, was passieren wird, wenn eine Java-Methode ein Java-Lambda zurückgibt. Was passiert, wenn eine Scala-Klasse diese Methode aufruft? Was wird der Rückgabetyp in Scala sein?
Giorgio
1
@Giorgio In Java 8 ist ein Lambda-Ausdruck eine Verknüpfung auf Sprachebene, um eine Instanz der Schnittstelle zu erstellen, die eine einzelne Methode deklariert und vom Kontext zurückgestellt wird. Wenn eine Java 8-Methode ein Lambda zurückgibt, gibt sie tatsächlich eine Instanz der Schnittstelle zurück, die als Rückgabetyp der Methode deklariert ist. Ab Scala 2.9.1 ist der Rückgabetyp lediglich eine Instanz einer Schnittstelle (z. B. Runnable oder Comparator), die Sie nicht als Scala-Lambda behandeln können, es sei denn, Sie oder zukünftige Versionen von Scala libary führen eine implizite Konvertierung daraus ein Schnittstelle zum Scala Lambda-Typ.
hellodanylo
@SkyDan: Ok, Scala sieht Java-Lambdas als Objekte, die eine Schnittstelle implementieren. Dieser Punkt war mir nicht klar: Ich dachte, Java würde einen Bytecode generieren, der sich von dem eines Objekts unterscheidet. Es muss sich jedoch um ein Objekt unter der Haube handeln, da es sonst nicht als Implementierung einer Schnittstelle erkannt wird. Ich glaube, ich habe es jetzt verstanden.
Giorgio
@Giorgio, auch wenn Sie mehr über Lambda-bezogene Änderungen in Java 8 und die Kräfte erfahren möchten, die diese Änderungen antreiben, empfehle ich Ihnen, diesen faszinierenden und detaillierten Überblick über das Lambda-Projekt zu lesen .
hellodanylo
@ SkyDan: Lies es jetzt. Es scheint mir , dass lambdas tun Objekte darstellen (auch wenn die Art / Schnittstelle aus dem Kontext zu entnehmen ist , in dem sie definiert sind). Die unter mail.openjdk.java.net/pipermail/lambda-dev/2011-August/… ("Lambdas sind keine Objekte") angegebenen Informationen sind daher falsch oder zumindest irreführend.
Giorgio