Der Typumwandlungsmechanismus in Java (type casting) ermöglicht es dem Programmierer, einen Wert eines Typs explizit oder implizit in einen anderen Typ umzuwandeln. Historisch ist diese Funktion von C und C++ geerbt, wurde jedoch in Java zur Erhöhung der Typsicherheit und zur Vermeidung versteckter Bugs, die mit Überlauf oder Datenverlust zusammenhängen, eingeschränkt.
Problem besteht in der Möglichkeit, dass bei der Umwandlung von Referenztypen eine ClassCastException auftritt, sowie in der Verlustgenauigkeit bei der Umwandlung von primitiven Typen, zum Beispiel beim Übergang von double zu int. Logische Fehler können bei der sogenannten "Downcasting" (Umwandlung in den abgeleiteten Typ) auftreten, wenn die Instanz nicht zu dieser Klasse gehört.
Lösung besteht in einer strengen Trennung:
Beispielcode für primitive Typen:
int i = 100; long l = i; // implizite Umwandlung (int -> long) double d = l; // implizite (long -> double) int i2 = (int) d; // explizite Umwandlung (Verlust des Dezimalteils)
Beispielcode für Referenztypen:
Object obj = "Hello"; // upcasting, implizit String s = (String) obj; // downcasting, explizit
Schlüsselmerkmale:
Kann der Java-Compiler fehlerhafte Typumwandlungen verhindern?
Antwort: Nein, der Compiler erkennt nur offensichtliche Fehler zur Kompilierungszeit. Wenn die Umwandlung in der Struktur der Typen möglich ist (zum Beispiel Object -> String), aber in der Variablen tatsächlich ein Objekt eines inkompatiblen Typs liegt, tritt der Fehler erst zur Laufzeit mit ClassCastException auf.
Erbt Integer von Long und kann ich schreiben Integer i = (Integer) someLong?
Antwort: Nein, Integer und Long sind unabhängige Wrapper-Klassen, zwischen ihnen kann kein Downcasting erfolgen. Beide erben von Number, aber nicht voneinander. Eine Umwandlung wie (Integer) (Object) 1L; führt zu einer ClassCastException.
Findet bei der expliziten Umwandlung von float zu int eine Rundung der Dezimalstelle statt?
Antwort: Nein, es findet eine Abschneidung der Dezimalstelle ohne Rundung statt:
float f = 3.99f; int i = (int) f; // i == 3, nicht 4
Ein Entwickler erhält eine Sammlung von Object, wandelt jedes Element in seinen Typ um, prüft jedoch nicht auf instanceof. Das Projekt stürzt stabil mit ClassCastException ab, wenn die Daten inkorrekt sind.
Vorteile:
Nachteile:
Alle Downcasting-Operationen werden innerhalb von if (obj instanceof TargetType) mit expliziter Fehlerrückmeldung durchgeführt. Für Sammlungen werden Generika verwendet.
Vorteile:
Nachteile: