Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.
Casten
Hi, kurz vor der Prüfung wollte ich nochmal fragen, wie das mit dem Casten so ist.
Ich habe zwei Klassen:
Ober{
}
Unter extends Ober{
}
Ist das hier:
Unter unter = new Unter();
Ober untercast = (Ober) unter;
äquivalent zu:
Ober oberunter = new Unter();?
Wenn nicht, wo ist genau der Unterschied?
Und wird bei einem Cast immer der dynamische und statische Typ “übernommen”?
Also ist in meinem Cast-Bsp. von oben der dynamische und der statische Typ Ober?
Ja, die beiden sind äquivalent. Das wird schnell klar, wenn man mal anfängt einzusetzen:
Unter unter = new Unter();
Ober untercast = (Ober) unter;
Den Cast sparen wir uns gleich mal, weil er an dieser Stelle auch automatisch passiert: [m]unter[/m] wird ja einer Variable vom Typ einer der Oberklassen von [m]Unter[/m] zugewiesen – der Compiler weiß schon beim compilieren, dass das immer funktionieren wird und braucht den Cast deswegen nicht. In die andere Richtung wäre er nötig und würde dann im Feherfall eine [m]ClassCastExcption[/m] werfen.
Außerdem setzen wir für [m]unter[/m] die Definition von [m]unter[/m] ein:
Ober untercast = new Unter();
und schon steht das gleiche da.
Der dynamische Typ eines Objekts bleibt immer gleich. Den statischen Typ kannst du durch casten ändern. Du kannst auch versuchen den statischen Typ auf einen Typ zu ändern, der nicht zum dynamischen passt – dann gibts aber zur Laufzeit eine [m]ClassCastException[/m] an der Stelle des casts. In deinem Beispiel ist der statische Typ [m]Ober[/m] und der dynamische Typ [m]Unter[/m].
Das bezieht sich aber schon nur auf’s Casten, richtig?
Wenn ich noch ne Klasse UnterUnter extends Unter hätte,
könnte ich doch folgendes machen:
Unter unter = new Unter();
UnterUnter unterunter = new UnterUnter();
unterunter = unter;
Dann ist doch der dynamische Typ nicht mehr UnterUnter sondern Unter, richtig?
die neue Klasse hätte ich gar nicht einführen müssen
Tipp: Einfach mal ausprobieren. [m]unterunter = unter;[/m] würde so nicht mal compilen (error: incompatible types) und wenn du es manuell castest (also [m]unterunter = (UnterUnter) unter;[/m]) wird es dir zur Laufzeit um die Ohren fliegen (ClassCastException).
Ach, mein Hirn ist einfach Matsch
Danke für die Hilfe. Hab’s ausprobiert und es ist natürlich so, wie du gesagt hast.
Ich mach mal ein Beispiel, bei dem das hoffentlich klarer wird:
[code=java]Ober ober = new Ober();
Unter unter = new Unter();
Ober variable;
variable = ober; // statischer Typ von variable ist Ober, dynamischer Typ ebenfalls
variable = unter; // statischer Typ bleibt gleich, dynamischer Typ ist Unter[/code]
Was ich eigentlich meinte ist, dass sich der Typ eines Objekts nie ändert – aber das ist ja auch nur logisch. Der dynamische Typ einer Variablen kann sich allerdings durchaus ändern (indem man der Variablen halt was neues zuweist). Der statische Typ einer Variablen ändert sich dahingegen wirklich nie – einmal deklariert bleibt der Typ immer der gleiche ([m]variable[/m] wird im Beispiel immer den statischen Typ [m]Ober[/m] haben).
Casts ändern den statischen Typ, allerdings nicht den statischen Typ von Variablen, sondern den von Ausdrücken:
Ober ober = new Unter();
ober.foo(); // in dieser Anweisung hat "ober" den statischen Typ Ober und den dynamischen Typ Unter
((Unter) ober).foo() // hier ist der statische Typ von "ober" immernoch Ober, der statische Typ von "((Unter) ober)" aber Unter. Der dynamische Typ bleibt in beiden Fällen Unter.
Wow, so hat das aber glaub ich noch niemand erklärt. Ist aber sehr einleuchtend.
Thx