为什么我得到这个ClassCastException?

时间:2010-01-04 20:02:17

标签: java casting

我有两个非常简单的类,一个扩展另一个:

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。这是为什么?

5 个答案:

答案 0 :(得分:7)

因为LocationType是超类;它不能转换为子类。

进一步解释一下:你只能编译继承树,也就是说,一个对象只能被转换为它创建的类类型,它的任何超类,或者它实现的任何接口。因此,String可以投放为StringObject; HashMap可以投放为HashMapAbstractMap MapObject

在您的情况下,MyLocationType可以是MyLocationTypeLocationType(或Object),但不是相反。

Java docs on inheritance非常好,只需在这里查看。

答案 1 :(得分:1)

这是因为LocationType不是MyLocationType的实例,而是它的父级。例如,如果您向[{1}}添加新方法,而不是MyLocationType,然后将LocationType转换为LocationType,如果调用了这些新方法,那么预期会发生什么基地MyLocationType

LocationType is a MyLocationTypeLocationType不是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)