Kann mir bitte jemand erklären, wie sich der Compiler im ersten Casting nicht beschwert, im zweiten aber?
interface I1 { }
interface I2 { }
class C1 implements I1 { }
class C2 implements I2 { }
public class Test{
public static void main(){
C1 o1 = new C1();
C2 o2 = new C2();
Integer o3 = new Integer(4);
I2 x = (I2)o1; //compiler does not complain
I2 y = (I2)o3; //compiler complains here !!
}
}
ClassCastException
: aRuntimeException
.ClassCastException
.Antworten:
Beim Casting
o1
undo3
mit(I2)
teilen Sie dem Compiler mit, dass die Klasse des Objekts tatsächlich eine Unterklasse des deklarierten Typs ist und dass diese Unterklasse implementiert wirdI2
.Die
Integer
Klasse ist endgültig undo3
kann daher keine Instanz einer Unterklasse von seinInteger
: Der Compiler weiß, dass Sie lügen.C1
ist jedoch nicht endgültig,o1
könnte also eine Instanz eines SubtypsC1
dieser Geräte seinI2
.Wenn Sie
C1
final machen , wird sich auch der Compiler beschweren:interface I1 { } interface I2 { } final class C1 implements I1 { } class C2 implements I2 { } public class Test{ public static void main(){ C1 o1 = new C1(); C2 o2 = new C2(); Integer o3 = new Integer(4); I2 y = (I2)o3; //compiler complains here !! I2 x = (I2)o1; //compiler complains too } }
quelle
Integer
endgültig ist (was für mich und Sie, aber wahrscheinlich nicht für alle offensichtlich ist) und der Teil "hat keine Chance, eine Schnittstelle zu sein" dies tut nicht zu viele Informationen tragen; Tatsächlich sind die fraglichen Informationen im zweiten Satz versteckt. Man könnte sogar denken, dassfinal
Klassen keine Inferfaces implementieren können, was nicht wahr ist.Gemäß JLS Kapitel 5
5.5.1. Referenztyp Casting
quelle
Das liegt daran, dass der Unterricht
Integer
endgültig ist undC1
nicht. Somit kann ein Integer-Objekt I2 nicht implementieren, während ein C1-Objekt dies könnte, wenn es eine Instanz einer Unterklasse von C1 ist, die I2 implementiert.quelle
Gemäß JLS 5.5.1 - Referenztyp-Guss gelten die folgenden Regeln:
Wenn T ein Klassentyp ist, dann entweder | S | <: | T | oder | T | <: | S |. Andernfalls tritt ein Fehler bei der Kompilierung auf.
I2 y = (I2)o3; //compiler complains here !!
In diesem Fall wird ein
Integer
undI2
sind in keinem Zusammenhang in irgendeiner Weise, so dass ein Fehler bei der Kompilierung auftritt. Auch, weilInteger
istfinal
, gibt es keine Beziehung zwischenInteger
undI2
.I2
undI1
kann in Beziehung gesetzt werden, da beide eine Markierungsschnittstelle sind (es gibt keinen Vertrag).Für den kompilierten Code gilt folgende Regel:
S
isto1
undT
istI2
.Hoffe das hilft.
quelle