Project Valhalla: Value Types in Java

Seite 2: Project Valhalla

Inhaltsverzeichnis

Diese Probleme hat auch das Java-Team bei Oracle erkannt und Maßnahmen ergriffen. Das Ziel von Project Valhalla ist es, benutzerdefinierte Werttypen als "first-class citizens" in die Sprache einzuführen. Dazu sind Änderungen einerseits an der Programmiersprache Java, andererseits an der JVM vorzunehmen. Im Folgenden geht es allein um die Modifikationen in der Sprache. Weil noch nicht klar ist, wie die endgültige Syntax aussehen wird, verwendet das Projekt eine bewusst hässliche Strohmann-Syntax. Damit will das Team Diskussionen dazu verschieben. Das Motto des Projekts ist: "Works like an int – codes like a class."

Wenn man sich ein Koordinatensystem vorstellt, dann ist eine Koordinate ein typischer Wert. Sie enthält zwei Felder, je eines für die Position auf der x- und auf der y-Achse. Mit der neuen Strohmann-Syntax wäre ein Werttyp Coordinate wie folgt zu implementieren:

final __ByValue class Coordinate {
private final int _x;
private final int _y;

public Coordinate(int x, int y) {
_x = x;
_y = y;
}

public boolean equals(Coordinate other) {
return _x == other._x
&& _y == other._y;
}
}

Dabei fällt sofort der Modifier __ByValue ins Auge. Hier soll ein neues Schlüsselwort eingeführt werden, dass eine Klasse als Werttyp kennzeichnet. Außerdem gelten die gleichen Randbedingungen wie für "value-based classes". Also nur finale Felder, die alle im Konstruktor zu initialisieren sind. Zustandsändernde Methoden sind verboten. Die Methode equals() vergleicht nur Felder und nicht Identitäten. Zusätzlich dürfen Werttypen keine Subtypen haben, sind also selbst auch final. Der Teil "...codes like a class" stimmt also.

Wie sieht es auf der Benutzungsseite aus? Gilt hier wirklich "Works like an int..."? Koordinaten kann man mit

Coordinate coordinate = __MakeValue(10, 8);

erzeugen. Hier gibt es wieder ein Strohmann-Schlüsselwort. Man kann sich fragen, ob das wirklich noch ein Erzeugen ist oder nicht mehr ein Belegen. Deshalb ist in Diskussion, wie __MakeValue umgesetzt werden wird. Analog zu Objekten ginge es mit new:

Coordinate coordinate = new Coordinate(10, 8);

Das ist aber irgendwie irreführend, weil ja nicht – wie new suggeriert – Speicher auf dem Heap belegt wird. Die zweite Möglichkeit ist deshalb, das Schlüsselwort einfach wegzulassen:

Coordinate coordinate = Coordinate(10, 8);

Und vielleicht sogar auch den Typ:

coordinate coordinate = (10, 8);

Das zugrunde liegende Problem ist, dass es keine Literale für selbstdefinierte Typen gibt.

Für den Speicher gilt mit Valhalla Folgendes: Die Exemplare von Werttypen liegen direkt im Speicher der Variable. So müssen sie nicht auf dem Heap sitzen, sondern können direkt im Stack existieren. Der Speicherbedarf für Referenzen entfällt. Außerdem ist kein Dereferenzierungsaufwand zu betreiben.

Die Operatoren "==" und "!=" sollen so implementiert werden, dass sie die Methode equals() aufrufen. Damit lassen sie sich für die Prüfung auf Gleichheit verwenden.

Eine weitere offene Frage ist noch, welchen Default-Wert Variablen von Werttypen haben. Bei Referenztypen ist der Standardwert "null", bei den eingebauten Typen "false" oder die passende Variante von 0. Die derzeit favorisierte Möglichkeit ist es, die Felder einer Wertvariablen wieder mit ihrem jeweiligen Default-Wert zu belegen. Der der Beispielklasse wäre dann Coordinate(0, 0).

Eine weitere spannende Frage ist, wie Value Types mit Generics zusammenspielen. Es besteht die Hoffnung, dass neben so etwas wie List<Coordinate> endlich List<int> möglich wird. Weil das größere Änderungen nach sich zieht, wurde hierfür der eigene JEP 218 (JDK Enhancement Proposal) aufgesetzt.

Offen ist auch noch, wie das Projekt mit Boxing umgeht. Für jeden eingebauten Typen gibt es einen Referenztypen, der beim Autoboxing zum Einsatz kommt (z. B. Float als Referenztyp für float). Beide kann man gut durch die Groß- und Kleinschreibung unterscheiden. Coordinate ist aber ja schon als Werttyp großgeschrieben. Wie der passende Referenztyp heißen wird, ist noch ungeklärt.