Ein Überblick über Java-Alternativen für den industriellen Einsatz | heise online

Ein Überblick über Java-Alternativen für den industriellen Einsatz

Lange hat sich in der Java-Welt wenig bewegt und immer wieder hochkochende Themen wie Modularisierung zeigen, dass Innovation in dem Gebiet alles andere als leicht fällt. Die Hoffnung ruht auf alternativen Sprachen.

vorlesen Druckansicht 49 Kommentare lesen
Lesezeit: 21 Min.
Von
  • Benjamin Schmid
Inhaltsverzeichnis

Lange hat sich in der Welt von Java wenig bewegt. Im März 2014 sollen die Closures aus Java 8 endlich wieder eine frische Brise aufkommen lassen. Aber schon das über acht Jahre alte und soeben neu aufgeflammte Debakel um die Java-Modularisierung Jigsaw zeigt, wie schwer den Machern auch in Zukunft größere Innovationen fallen dürften. Doch es gibt Hoffnung. Alternative Sprachen für die JVM versprechen neue Programmierparadigmen, prägnanteren Code und mehr Flexibilität.

Für den industriellen Einsatz sind insbesondere die neu am Horizont auftretenden Vertreter statisch und streng typisierter Programmiersprachen interessant. Ihre Prüfungen zur Entwurfszeit und Garantien zur Laufzeit bieten komplexen Umfeldern größere Sicherheiten und machen sie damit zu direkten Konkurrenten für Java. Zeit, sich einen Überblick über die wichtigsten Kandidaten zu verschaffen.

Im Zusammenhang mit neuen Programmiersprachen wird ein Thema häufig als Erstes genannt: "Funktionale Programmierung". Dabei ist die rein funktionale Programmierung ein ziemlicher Exot und zudem für viele Entwickler recht ungewohnt. Allgemein sind daher eher multi-paradigmische Sprachen gemeint, die unter anderem die Elemente funktionaler Programmierung in sich vereinen.

Doch wozu das alles? Funktionale Sprachmittel ermöglichen in bestimmten Konstellationen eine erheblich effizientere Programmierung. Auch Java 8 führt mit Closures ein wichtiges funktionales Feature ein. Das folgende Beispiel illustriert den Unterschied anhand des Sortierens einer Liste:

// "Klassisches" Sortieren einer Liste mittels Comparator 
Collections.sort(listOfCars, new Comparator<Car>(){
public int compare(Car c1, Car c2){
return p1.maker.compareTo(p2.maker);
}
});

Mit Closures unter Java 8 lässt sich die Aufgabe dagegen ungleich prägnanter lösen:

// Sortieren einer Liste mittels Lambda-Ausdruck
listOfCars.sort((c1, c2) -> c1.maker.compareTo(c2.maker));

Gleich vorweg: Alle der hier vorgestellten Sprachen sind funktional und gehen dabei deutlich über die in Java 8 gebotenen Mittel hinaus. Letztendlich liegen die Unterschiede jedoch im Detail, sodass sich eine nähere Einzelbetrachtung anbietet.

Die vor über 10 Jahren von der Schweizer Universität EPFL (École polytechnique fédérale de Lausanne) ins Leben gerufene Sprache Scala gehört fraglos zu den Urgesteinen unter den alternativen JVM-Sprachen und konnte sich mittlerweile sogar in größeren Unternehmen etablieren. Scala vereint dabei so kompromisslos wie keine andere Sprache funktionale mit objektorientierten Konzepten. Ihren akademischen Ursprung kann sie dabei nicht verleugnen. Insbesondere Menschen mit mathematischem Hintergrund werden sich hier schnell wohlfühlen. Die große Mächtigkeit von Scala hat jedoch auch ihre Schattenseiten und führt dazu, dass Entwickler sie oft mit einer steilen Lernkurve und einer gewissen Komplexität assoziieren.

Neben den Sprachfeatures und den Werkzeugen spielt das Umfeld eine gewichtige Rolle für eine Programmiersprache. In dem Punkt kann Scala mit einem lebendigem Ökosystem an Literatur, Frameworks und Konferenzen mächtig punkten. Im Jahr 2011 gründete sich zudem die Firma Typesafe mit drei Millionen Dollar frischem Risikokapital und bekannten Java-Größen wie Doug Lea und James Gosling als Berater. Damit steht auch hinter Scala und seinen populären Frameworks Play und Akka ein kommerzielles Unternehmen.

Im Vergleich zu Java präsentiert sich Scala erst einmal syntaktisch deutlich vielfältiger: Semikolons am Zeilenende sind optional, am Aufruf von Methoden können die Punkte und Klammern entfallen und sämtliche Operatoren stellen nichts anderes als austauschbare Methoden dar. Seinen funktionalen Wurzeln entsprechend, besitzt jeder Ausdruck einen Rückgabewert. Wie auch die anderen Vertreter in diesem Artikel nutzt Scala First-class Functions, was heißt, dass sich Funktionen wie normale Objekte weiterreichen und ablegen lassen.

Besonders zeichnet Scala jedoch sein mächtiges Typ-System aus: So können generische Klassen über Annotation beschreiben, an welchen Stellen Untertypen ihrer Typparameter verwendet werden dürfen und welche Auswirkungen das hat. Diese Lösung für die als Ko- und Kontravarianz bezeichnete Problemstellung ist jedoch so mächtig, dass ein Projekt sie scherzhaft aufgegriffen und auf ihrer Basis eine vollständige Turing Maschinerealisiert hat, was eine gewisse Komplexität durchaus belegt.

Dagegen gehören die sogenannten Traits in Scala zu den einfacheren und dennoch leistungsfähigen Konzepten. Traits sind in Scala Schnittstellendefinitionen, die optionale Standardimplementierungen mitbringen dürfen. Das vermeidet die Komplexität echter Mehrfachvererbung und erlaubt trotzdem ein einfaches Wiederverwenden von Logik über Typen hinweg.

trait Similarity { 
def isSimilar(x: Any): Boolean
def isNotSimilar(x: Any): Boolean = !isSimilar(x)
}

Ein sehr mächtiges Feature von Scala sind die sogenannten Implicit Conversions. Damit lassen sich implizite automatische Typkonvertierungen formulieren. Hat man nun zum Beispiel ein Objekt vom Typ Color und weist ihn einer als String typisierte Variable zu, ruft Scala im Hintergrund passend definierte Konvertierungsfunktionen auf, ohne den Entwickler mit der Diskrepanz zwischen erwartetem und tatsächlich vorhandenem Typ konfrontieren zu müssen. Soviel Komfort das auf der einen Seite bedeutet, so sehr kann es die tatsächliche Vorgehensweise einer Funktion stark verschleiern, wie das folgende Beispiel illustriert.

object Color { 
implicit def colorToString(c: Color) : String = {
toString() }
}

// Valider Aufruf an anderer Stelle
val s : String = new Color()

Obwohl Scala schon recht lange in einer stabilen Version vorliegt und produktiv eingesetzt wird, gab es in der Vergangenheit regelmäßig nicht abwärtskompatible Änderungen. Insbesondere der erzeugte Bytecode zeigte sich manchmal wenig stabil.

So beklagte sich Ende 2011 der Entwickler des populären Scala Web Frameworks "Lift", dass sämtlicher Scala-Code einer Anwendung, also auch der aus Dritt-Bibliotheken, letztlich vollständig mit exakt derselben Scala-Version zu übersetzen ist, damit das Gesamtsystem zuverlässig funktioniert. Das würde das Unternehmensargument ad absurdum führen. Typesafe hat auf das Problem reagiert, indem es mit dem Migration Manager ein dediziertes Werkzeug anbietet, das Inkompatibilitäten zwischen unterschiedlichen Scala-Versionen im Bytecode prüfen kann.

Scala kann folglich sowohl Offenbarung als auch Herausforderung sein. Im Alltag erlebt man öfters, dass die Fehlerquelle nicht immer der Mensch ist. So meckert die IDE manchmal auch korrekten Code als falsch an oder mag nicht mehr recht darin navigieren. Ist man jedoch in der Lage, die Möglichkeiten der Plattform gut zu nutzen, gehört Scala in jedem Fall zu den spannenden Alternativen gegenüber Java.

Ein echter Underdog dagegen ist die nur zwei Jahre jüngere Sprache Fantom. Ihre Entwickler Brian und Andy Frank setzen einige spannende und innovative Konzepte um, die zum Teil auch anderen Sprachen gut zu Gesicht stehen würden.

Im Fokus der Brüder stand der Entwurf einer portablen und eleganten Sprache mit einer um innovative Konzepte angereicherten, eingängigen Syntax. So kann auch Fantom mit allen wichtigen Buzzwords wie First-class Functions, Type Inference und Mixins aufwarten. Mit Portabilität als vorrangigem Ziel nutzt Fantom ein eigenes Interims-Byteformat fcode, das erst zur Laufzeit in den Java- respektive .NET-Bytecode überführt wird. Ähnlich wie bei Kotlin und Ceylon gehört auch JavaScript zu den Zielplattformen – derzeit allerdings noch auf experimentellen Niveau. Damit die Portabilität nicht an plattformspezifischen APIs scheitert, steckten die Entwickler ihre – nach eigenen Aussagen geradezu "obsessive" – Energie in die Gestaltung der spracheigenen Standardbibliotheken, die zwar vergleichsweise wenige, dafür aber sehr elegante und leistungsfähige Klassen bieten.

Streng genommen sprengt Fantom ein bisschen den Rahmen der statisch typisierten Sprachen, da es in Teilen auch eine dynamische Typisierung unterstützt. Zwar zwingt die Sprache den Entwickler, sich für Felder und Methodensignaturen auf Typen und damit einen klaren Schnittstellenvertrag festzulegen, fährt aber ansonsten eher eine "Laissez-fair attitude" was die Typsicherheit betrifft.

Damit entfällt zum Beispiel komplett das aus Java bekannte Typisieren (Typecast). Wenn an einer Stelle eine Spezialisierung des Typs erwartet wird, castet die Sprache, gegebenenfalls ungeprüft, auf ihn. Nur wenn sich der erwarte und der vorhandene Typ zur Laufzeit nicht gesichert ineinander überführen lassen, wirft der Compiler einen Fehler.

// Eine Funktion die ein Int erwartet
Int quadriere(Int x) { ... }

// Statische Typprüfung: zweifelsfrei richtig
Int i := 5
quadriere(i)

// Potentiell richtig; es wird automatisch gecastet
Num n := 5
quadriere(n)

// Komplierfehler: Ein Str kann kein Int sein
Str s := "foo"
quadriere(s)

Leider kommt die beschriebene Vorgehensweise auch an anderer Stelle zum Einsatz, wo sie weniger geschickt ist: Fantom bietet mit Nullability eine Option, um zu unterscheiden, ob ein Typ null enthalten darf oder nicht. In der Regel ist man so sicher, immer einen Wert in der Hand zu haben. Allerdings führt Fantom auch für solche Typen eine implizite Konvertierung aus, womit diese Sicherheit wiederum leicht verloren geht.

Ein zur Geburtsstunde von Java noch unerwarteter Trend ist die rasante Entwicklung Richtung Mehrkern-Prozessoren, der den Einsatz nebenläufiger Programmierung notwendig macht. Mit den Concurrency Utilities hat Java durchaus ein solides Rahmenwerk zu bieten, allerdings kann es mit den klassischen Paradigmen schnell schwierig werden, nicht den Überblick zu verlieren. Hier zeigt Fantom nicht nur Java, wie es besser gehen könnte.

Im Kontrast zu den klassischen Ansätzen gibt es unter Fantom keinen geteilten Speicher zwischen zwei Threads. Jeder Thread kann stets nur seine eigenen Variablen sehen. Vergleichbar mit dem Akka-Framework in Scala kommt stattdessen ein Aktoren nutzendes Modell zum Einsatz: Voneinander unabhängige Aktoren tauschen asynchron unveränderbare Nachrichten miteinander aus und nutzen sonst keinerlei gemeinsame Zustände oder Synchronisationsmechanismen. Dieses im Kern recht einfache Konzept nimmt viel von der Komplexität bei der Entwicklung nebenläufiger Ansätze und erlaubt zugleich eine flexible Skalierbarkeit über Rechnergrenzen hinweg. Die Verankerung direkt im Sprachkern macht es zudem in seiner Verwendung so sicher wie kaum eine andere Herangehensweise.

Auch bei Generics zeigt sich Fantom individuell: Es gibt keine. Zwar besitzen Standardtypen für Listen und Maps durchaus Typparameter, abgesehen davon verzichtete Fantom jedoch zugunsten einer einfacheren Verwendung komplett auf Generics.

Insgesamt vermittelt die Sprache das Bild eines kleinen und durchdachten Gesamtpakets. In dem nur 15 MB großen Download bringt es ein eigenes Build- und ein Package-Management-System, ein plattformunabhängiges GUI-Kit und einige Beispiele inklusive einer Hello-World-Webanwendung samt minimalen Webserver mit. Gerade der in sich geschlossene und konsistente Rahmen ist eine erfrischende Gegenerfahrung zu den überbordenden Technologie- und Framework-Konglomeraten der Java-Welt. Auf der anderen Seite ist das allerdings der größte Pferdefuß der Sprache: Eine echte IDE gibt es nicht, alle Teile beschränken sich auf das Wesentliche und trotz seiner vergleichsweise langen Historie konnte Fantom nie wirkliche Relevanz erreichen. Schade eigentlich, denn die vielen innovativen und pfiffigen Ansätze zeigen, dass Fortschritt bei Programmiersprachen nicht zwangsläufig mehr Komplexität bedeuten muss.

Wenn jemand Erfahrung im Umgang mit JVM-basierten Programmiersprachen hat, dann JetBrains. Als Hersteller zahlreicher Entwicklungsumgebung für die unterschiedlichsten Sprachen hat die tschechische Softwareschmiede eine beachtliche Java-Codebasis aufzuweisen. Daher stellt das für den industriellen Einsatz vorgesehene Kotlin von Beginn an exzellente Java-Interoperabilität, eine gute Tool-Unterstützung, Performance sowie das richtige Maß an Abstraktion für eine ausdrucksstarke und dennoch gut lesbare und sichere Sprache an oberste Stelle.

Der Fokus auf Robustheit zeigt sich auch in der Roadmap: "It's ready when it's done" ist die erklärte Devise für die seit 2010 laufende Entwicklung. So setzt man auf eine ausführliche Beta-Phase samt intensiver Nutzung im eigenen Hause, bevor Kotlin den Status einer stabilen 1.0 erhalten soll. Der aktuelle Meilenstein M6.2 hat bereits durchaus eine produktionstaugliche Reife erlangt und bringt zudem Support für Googles neues Android Studio mit.

Naturgemäß wird die Entwicklung vorrangig durch JetBrains selbst vorangetrieben, jedoch ist das Projekt offen gegenüber Anregungen und Code-Beiträgen neuer "Kontributoren". Dem Firmenhintergrund ist wohl auch das große Momentum in der Entwicklung zuzurechnen. So kann Kotlin bereits mit einer überdurchschnittlich guten IDE-Integration in das Hausprodukt IntelliJ IDEA aufwarten. Kotlin steht, wie auch die Open-Source-Variante der Entwicklungsumgebung, vollständig unter der freien Apache-Lizenz. Ein Eclipse-Plug-in ist vorerst nur in Aussicht gestellt.

Beim Entwurf der Sprache folgte man unverkennbar einem pragmatischen Ansatz und griff sich als eine noch eher junge Sprache einfach die besten Aspekte der Mitbewerber heraus. So findet man etwa die bekannten Traits aus Scala wieder. Aus der .NET-Welt sind Extension Methods bekannt, mit denen sich eigene Methoden an fremde Klassen hängen lassen. Zusammen mit einer Literale nutzenden Kurzschreibweise lassen sich damit die aus Groovy bekannten Builder für eigene domänenspezifische Sprachen (DSL) realisieren, die zudem typsicher sind.

Wie alle hier vorgestellten Sprachen bringt auch Kotlin eine eigene Laufzeit-Bibliothek mit. Statt aber zum Beispiel das Collections-Framework von Java durch eigene Implementierungen zu ersetzen, nutzt und ergänzt sie diese. Damit gestaltet sich die Integration mit Java-Bibliotheken unvergleichbar nahtlos.

Die NullPointerException dürfte in typischen Java-Anwendungen unangefochtener Spitzenreiter als Auslöser vieler Fehlerberichte sein. Hier bietet Kotlin eine elegante und sichere Lösung: Die Sprache unterscheidet explizit zwischen optionalen Typen, die null enthalten dürfen, und den normalen Typen mit Pflichtwert. Ungeprüfte Dereferenzierungen auf optionale Typen meckert der Compiler an.

Deshalb müssen die potenziellen Fehlerpfade stets überprüft und behandelt werden. Der Umgang mit diesen optionalen Werten stellt sich im weiteren Verlauf aber als erstaunlich komfortabel dar. So erkennt Kotlin zum Beispiel umschließende Null-Prüfungen und überführt mittels Smart Cast den Wert automatisch in den Null-freien Typ. Mittels Kurzschreibweisen entfallen auch viele der sonst unter Java mühsamen und länglichen if/else-Blöcke für die Null-Behandlung zugunsten weniger zusätzlicher Zeichen.

fun GeneralNullsafety() {

//val o: String = null // Compilerfehler
val s: String? = null

//s.hashCode() // Compilerfehler
s?.hashCode() // Safecall

if (s != null) { // Smart cast:
s.hashCode() // String? -> String
}

// null-Alternativwert via Elvis-Operator ?:
val r = s?.substring(2) ?: "n/a"
r.hashCode()
}

Beim Aufruf von Java-Code nimmt Kotlin für Rückgabewerte erst einmal stets optionale Typen an. Mit dem KAnnotator gibt es jedoch ein Werkzeug, das über statische Bytecode-Analyse versucht, jene Stellen zu identifizieren, bei denen die Rückgabe eines Wertes garantiert ist. So lassen sich auch Java-Klassen komfortabel verwenden, ohne Gefahr zu laufen, sich die neuralgische Fehlerquelle wieder neu einzufangen.

Daneben kann Kotlin noch weitere interessante Sprachmerkmale bieten, etwa die sogenannten Delegated Properties. Wer hier mehr sehen will, wirft am besten einen Blick auf die Online-Demo, in der sich Code-Beispiele verändern und durch die Option, nach JavaScript zu übersetzen, nativ im Browser ausführen lassen.

Lange Zeit war die Schöpfung aus dem Haus Red Hat eher nebulös und beschränkte sich auf Ankündigungen und eine grobe Sprachdefinition von Seiten ihres Schöpfers, dem Hibernate-Erfinder Gavin King. Inzwischen hat sich jedoch einiges getan und so hat das Projekt nach gut drei Jahren überraschend schnell seinen ersten, Feature-vollständigen 1.0.0 Stand veröffentlicht. Damit kann der junge Sprössling mit schicker Website, einem funktionierenden Compiler, IDE-Plug-in für Eclipse und einer kleineren Online-Demo aufwarten.

Die erklärten Ziele des Projekts sind es, eine Alternative zu Java mit gewohnter, gut lesbarer Syntax und fortschrittlicheren Sprach-Features zu bieten, die sich zudem für den Einsatz in Teams und Großprojekten eignet. Auch Ceylon bringt Higher-order Functions, Null-Sicherheit, Mixins und JavaScript als zusätzliche Laufzeitumgebung an den Tisch. Zudem bemüht sich die Sprache um ein einfacheres, aber dennoch leistungsfähiges Typ-System.

Wie auch in Kotlin legt der Zusatz in beziehungsweise out eines Typ-Parameter fest, ob die generische Klasse diese Typen lesen oder erzeugen darf.

shared interface Erzeuger<out Ausgabe> {
shared formal Iterator<Ausgabe> iterator();
}
shared interface Consumer<in Eingabe> {
shared formal void add(Eingabe x);
}

Weicht man davon ab, erhält man einen Compiler-Fehler. Und schon ist das Problem der Ko- und Kontravarianz gebannt, das Java die undurchsichtigen Generics-Wildcards und Scala die Turing- Vollständigkeit bescherte. Ein Alleinstellungsmerkmal ist bislang, dass Ceylon sogenannte Reified Generics bietet. Sie sind dafür verantwortlich, dass die Typparameter auch noch zur Laufzeit verfügbar sind, und ermöglichen so zum Beispiel das Erzeugen neuer Instanzen.

Ceylon legt explizit Wert darauf, dass sich jeder Typ auch mit Mitteln der Sprachen selbst ausdrücken lässt. Das klingt zunächst selbstverständlich, ist aber dank der Generics seit Java 5 in einzelnen Compiler-Fehlermeldungen nicht mehr gegeben. Die sogenannten Union Types und Intersection Types sind in Ceylon wichtige Bausteine um dies zu erreichen. Sie beschreiben Typen, die sich aus der Vereinigungs- beziehungsweise Schnittmenge anderer ergeben. Ein Beispiel: Eine Variable vom Typ String|Integer|Float akzeptiert also jede Instanz, die einer dieser drei numerischen Typen erfüllt. Der Typ Einkaufskorb&Iterable akzeptiert dagegen nur Werte, die gleichzeitig "Einkaufskorb" und "Iterable" sind.

Das Typsystem ebnet zudem den Weg für eine einfache Behandlung von Nullwerten. Letztere tragen in Ceylon einen eigenen Typ Null, der genau eine Instanz Null.null besitzt. Damit sich einer Variable also Null zuordnen lässt, muss sie den entsprechenden Typ haben. Im Beispiel also String|Integer|Float|Null. Damit ist die Behandlung von optionalen Werten deutlich besser als beispielsweise in Scala. An den Komfort von Kotlin reicht der Ansatz nicht ganz heran.

Eine Stärke ist bei Ceylon das eigene Modulsystem. Ceylon Module definieren explizit ihre Abhängigkeiten samt Versionsnummer. Ein eigenes Archivformat (.CAR) und die Laufzeitumgebung sorgen dafür, dass auch transitive Abhängigkeiten geladen werden, die Module ansonsten jedoch vollständig voneinander isoliert bleiben.

Was die Interoperabilität mit Java anbelangt, versäumte das Projekt es jedoch anfangs, klare Aussagen zu treffen. Interoperabilität sei eine "wichtige Priorität", der Bruch mit dem Java SDK aber notwendig, hieß es. Die Entwickler rieten zu explizit für die Sprache entwickelten Frameworks. Inzwischen ist das Projekt hier nicht mehr ganz so rigoros und betont, dass auch der Zugriff auf Java-Klassen möglich ist.

Spannend sind alle vorgestellten Java-Konkurrenten. Allerdings ist entscheidend, inwieweit sie auch von Unternehmen akzeptiert und eingesetzt werden.

Hier hat Scala eindeutig den Vorteil seiner längeren Historie und nimmt aktuell die Position des Platzhirsches ein. Die mächtige Sprache aus akademischer Feder kann mit bekannten Frameworks wie Play und Akka und einer jahrelangen Erprobung in der Praxis aufwarten. Dennoch konnte sie sich bislang nicht wirklich in der Breite durchsetzen, was neben einer gewissen Risikoscheu vielleicht auch der erforderlichen Lernkurve und dem Thema Interoperabilität geschuldet sein mag.

Fantom bietet dagegen eine erfrischende Erfahrung und inspiriert mit seiner Einfachheit und den vielen Details. Für den kommerziellen Einsatz ist und bleibt es jedoch zu sehr Exot, wenngleich sein Mittelweg zwischen statischen und dynamischen Konzepten durchaus eine gewisse Attraktivität besitzt.

Das junge Kotlin besticht mit pragmatischen Ansätzen, starken Tools und vor allem der Betonung der Stabilität und vollständiger Java-Interoperabilität. Mit seinem attraktiven Funktionsumfang und der dennoch guten Lesbarkeit fühlt es sich wie die natürliche Fortsetzung von Java in Form eines neuen "Java++" an. Mit dem kommerziellem Hintergrund und der damit verbundenen Entwicklungsdynamik gehört Kotlin somit definitiv an die oberen Stellen der Watchlist. Ein kleineres Hindernis könnte der versprochene, aber noch ausstehende Support der in Unternehmen verbreiteten Eclipse-IDE sein.

In letzter Zeit macht Ceylon mehr Reden von sich, das mit Red Hat ebenfalls eine größere Firma als Sponsor hat, dabei aber deutlich mehr auf seine Community und den Open-Source-Gedanken setzt. Es bringt eine attraktive Mischung aus Altbekanntem und Neuem in gewohnter, folglich längerer Syntax mit. Kapitaler wiegt dagegen, dass Ceylon alte Zöpfe abschneiden möchte und daher breiter mit dem Java SDK und dem zugehörigen Ökosystem bricht. Zudem ist es noch recht jung und ohne große Praxistests, sieht sich aber dennoch schon als für den Produktiveinsatz reif.

Java Scala Fantom Ceylon Kotlin
Statische Typisierung + + (+) + +
Funktionen höherer Ordnung (-) + + + +
Mixins/Traits - + + + +
Extension Methods - + - (-) +
Implizite Casts - (+) + - (+)
Pattern Matching - + - - (+)
Cross-Compiling - (.NET) JS, (.NET) JS JS
Promote Immutability - + + (+) -
Module (-) - + + (+)
Nullables - (x) + + +
Reified Generics - - n/a + -


Eines wird jedoch klar: Die Lust auf Innovationen und neue Effizienz ist groß. Ob es Java gelingt, hier seine Attraktivität wieder auszubauen oder der Raum für Herausforderer weiterhin offen bleibt, ist derzeit spannender denn je. Denn mit den vitalen Neulingen in den Startlöchern kommt auf jeden Fall eines auf: Frischer Wind!

Benjamin Schmid
ist ein Anhänger sauberen Programmcodes und betreut seine Kollegen als Technology Advisor bei der eXXcellent solutions GmbH in allen technologischen und methodischen Fragestellungen.

Siehe dazu auch

Einführung in die Programmierung mit Kotlin, PDF, 7,99 Euro (jul)