Mit Casting bezeichnet man in der Programmierung die Umwandlung des Wertes einer Variable in einen anderen Typ.
Implizites Casting geschieht immer dann, wenn man einer Variablen einen Wert zuweist, der nicht dem der Variablen entspricht.
int i = 15;
double d = i;
Die interne bitweise Darstellung der Zahl 15
als Dezimalzahl und
als Gleitkommazahl sind sicherlich verschieden, da eine Gleitkommazahl aus
Mantisse und Exponent besteht (in diesem Fall 0.15e+2
, und das
dann noch binär). Deshalb muss die Zahl umgerechnet werden. Die
Umrechnung geschieht in diesem Fall automatisch. Bei den primitiven Datentypen
erfolgt implizites Casting in dieser Richtung:
byte -> short -> int -> long -> float -> double
d.h. wenn der Zieltyp "grösser" ist als der aktuelle Wert und deshalb keine Informationen durch Rundung verloren gehen. Wenn man versucht einen Wert einer Variablen mit "kleinerem" Typ zuzuordnen, erfolgt eine Fehlermeldung vom Compiler. Bei einer solchen Operation muss das Casting explizit erfolgen.
Tutor04.java:20: possible loss of precision
found : double
required: int
i = d;
^
1 error
Na wenn dass nicht mal eine exakte und verständliche Fehlermeldung ist, grosses Kompliment an die Entwickler der Java-Compilers.
Explizites Casting erfolgt durch die Angabe des Zieltyps in Klammern vor dem Ausdruck.
i = (int) d;
Explizites Casting muss immer dann erfolgen, wenn bei der Typumwandlung Informationen verloren gehen können, z.B. bei einer solchen Zuweisung:
i = (int) 10.8; // dies ergibt 10
i = (int) -10.8; // dies ergibt -10
Beim Casting auf ganze Zahlen werden die Nachkommastellen abgeschnitten, d.h. es wird immer zur Null hin gerundet.
Natürlich darf man auch explizit casten, wo es eigentlich nicht nötig ist.
d = (double) i;
i = (int) 15;
Bei Objekten funktioniert das genauso. Auf Vererbung wird in LektionB3 eingegangen. Die Umwandlung des Typs eines Objektes in eine Superklasse kann implizit erfolgen. Umkegehrt muss der Typ angegeben werden. Sei folgende Klassenhirarchie gegeben:
class A {
public void foo(A a) { ... }
...
}
class B extends A { ... }
class C extends A { ... }
Alle Objekte vom Typ B
und C
können implizit
in den Typ A
gecastet werden.
B b = new B();
C c = new C();
A a = b; // implizites Casting von b nach A
a.foo(c); // implizites Casting von c nach A
Um eine (zuvor "runtergecastete") Variable in einen "höheren" Typ umzuwandeln muss explizit gecastet werden.
b = (B) a;
c = (C) a; // throws ClassCastException
Da das Objekt a
eigentlich vom Typ B
ist, kann es
auch in diesen Typ gecastet werden. Mit dem Typ C
funktioniert
das nicht. Der Compiler kann so etwas nicht bemerken. Solche Fehler werden zur
Laufzeit mit einer ClassCastException
bestraft. Damit man sich
mit der Exception nich herumschlagen muss, gibt es in Java einen Operator, der
prüft, ob sich ein Objekt in einen bestimmten Typ umwandeln lässt
(das funktioniert genau für die Klassen, die oberhalb des Objektes im
Hierarchiebaum liegen).
System.out.println(a instanceof B); // ergibt true
System.out.println(a instanceof C); // ergibt false
Eine übliche Abfrage sieht so aus:
if (a instanceof B) {
b = (B) a;
} else {
b = null;
System.out.println("Typumwandlung nicht möglich");
}
Wer das Beispiel mit den Klassen nicht versteht, dazu wird es auch noch eine Lektion geben. Gleiches gilt für Exceptions.