我有两个非常简单的类,一个扩展另一个:
public class LocationType implements Parcelable {
protected int locid = -1;
protected String desc = "";
protected String dir = "";
protected double lat = -1000;
protected double lng = -1000;
public LocationType() {}
public int getLocid() {
return locid;
}
public void setLocid(int value) {
this.locid = value;
}
public String getDesc() {
return desc;
}
public void setDesc(String value) {
this.desc = value;
}
public String getDir() {
return dir;
}
public void setDir(String value) {
this.dir = value;
}
public double getLat() {
return lat;
}
public void setLat(double value) {
this.lat = value;
}
public double getLng() {
return lng;
}
public void setLng(double value) {
this.lng = value;
}
// **********************************************
// for implementing Parcelable
// **********************************************
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt (locid);
dest.writeString(desc );
dest.writeString(dir );
dest.writeDouble(lat );
dest.writeDouble(lng );
}
public static final Parcelable.Creator<LocationType> CREATOR = new Parcelable.Creator<LocationType>() {
public LocationType createFromParcel(Parcel in) {
return new LocationType(in);
}
public LocationType[] newArray(int size) {
return new LocationType[size];
}
};
private LocationType(Parcel dest) {
locid = dest.readInt ();
desc = dest.readString();
dir = dest.readString();
lat = dest.readDouble();
lng = dest.readDouble();
}
}
和
public class MyLocationType extends LocationType {
private ArrayList<ArrivalType> mArrivals = new ArrayList<ArrivalType>();
public List<ArrivalType> getArrivals() {
return mArrivals;
}
public void addArrival(ArrivalType arrival) {
mArrivals.add(arrival);
}
}
问题在于,当我将LocationType
的实例投射到MyLocationType
时,我得到ClassCastException。这是为什么?
答案 0 :(得分:7)
因为LocationType
是超类;它不能转换为子类。
进一步解释一下:你只能编译继承树,也就是说,一个对象只能被转换为它创建的类类型,它的任何超类,或者它实现的任何接口。因此,String
可以投放为String
或Object
; HashMap
可以投放为HashMap
,AbstractMap
Map
或Object
。
在您的情况下,MyLocationType
可以是MyLocationType
或LocationType
(或Object
),但不是相反。
Java docs on inheritance非常好,只需在这里查看。
答案 1 :(得分:1)
这是因为LocationType
不是MyLocationType
的实例,而是它的父级。例如,如果您向[{1}}添加新方法,而不是MyLocationType
,然后将LocationType
转换为LocationType
,如果调用了这些新方法,那么预期会发生什么基地MyLocationType
?
LocationType
is a MyLocationType
但LocationType
不是LocationType
。
答案 2 :(得分:1)
因为MyLocationType
的类型为LocationType
且可以转换为一个,但LocationType
<{1}},因此无法投放它。
答案 3 :(得分:1)
LocationType lt = new LocationType();
MyLocationType myLt = new MyLocationType();
LocationType t1 = (LocationType)lt; // OK, but cast not required
LocationType t2 = (LocationType)myLt; // OK, but cast ALSO not required
MyLocationType t3 = (MyLocationType)lt;
// ClassCastException, MyLocationType extends (is-a) LocationType,
// not the other way around
MyLocationType t3 = (MyLocationType)lt;
MyLocationType t5 = (MyLocationType)myLt; // OK, but cast not nessecary
几乎从不需要显式地抛弃树,并且树上有风险:
public void doThis(LocationType lt) {
MyLocationType myLt = (MyLocationType)lt; // DANGEROUS
}
只有在使用某种方法覆盖某个方法时才能执行此类操作 签名,即使这样你也应该检查:
@Override
public void doThis(LocationType lt) {
if (lt instanceof MyLocationType) {
MyLocationType myLt = (MyLocationType)lt;
} else {
// A LocationType but not MyLocationType
doSomethingElse(lt);
}
}
答案 4 :(得分:0)
因为您尝试的参考是不 MyLocationType的实例
此示例总是帮助我思考正在发生的事情。
Object o = new Object();
String s = ( String ) o;
尽管String继承自Object并不意味着每个Object都是一个字符串(或者在这种情况下,“casted”对象是一个String)