I have two very simple classes, one extends the other:
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.rea开发者_JS百科dDouble();
}
}
and:
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);
}
}
The problem is that when I cast an instance of LocationType
to MyLocationType
I get a ClassCastException. Why is this?
Because LocationType
is the superclass; it can't be cast to the subclass.
To explain a bit further: you can only cast up the inheritance tree, which is to say, an object can only be cast as the class type it was created as, any of its superclasses, or any interface that it implements. Thus, a String
can be cast as either a String
or an Object
; a HashMap
can be cast as a HashMap
, an AbstractMap
Map
, or an Object
.
In your case, a MyLocationType
can be either a MyLocationType
or a LocationType
(or an Object
), but not the other way around.
The Java docs on inheritance are pretty good, just to review here.
This is because LocationType
is not an instance of MyLocationType
it is it's parent. For example if you added new methods to MyLocationType
not in LocationType
and then cast LocationType
to MyLocationType
what would expect to happen if these new methods were called that do not exist in the base LocationType
?
MyLocationType
is a LocationType
but LocationType
is not a MyLocationType
.
Because MyLocationType
is of type LocationType
and can be cast to one, but LocationType
is not of MyLocationType
and therefor cannot be cast to it.
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
explicit casting down the tree is almost never required, and up the tree is risky:
public void doThis(LocationType lt) {
MyLocationType myLt = (MyLocationType)lt; // DANGEROUS
}
this kind of stuff should only be done if you override a method with a certain signature, and even then you should check:
@Override
public void doThis(LocationType lt) {
if (lt instanceof MyLocationType) {
MyLocationType myLt = (MyLocationType)lt;
} else {
// A LocationType but not MyLocationType
doSomethingElse(lt);
}
}
Because the reference you're trying to case is not an instance of MyLocationType
This sample always help me to think what's happening.
Object o = new Object();
String s = ( String ) o;
Although String inherits from Object that doesn't mean that every Object is an string ( or in this case, that the "casted" object is an String )
精彩评论