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

Seite 5: Ceylon

Inhaltsverzeichnis

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.