2010-01-04 76 views
2

我有兩個非常簡單的類,一個擴展其他:爲什麼我得到這個ClassCastException?

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。爲什麼是這樣?

回答

7

因爲LocationType是超類;它不能被轉換爲子類。要進一步解釋:只能建立繼承樹,也就是說,只能將對象轉換爲創建的類類型,其任何超類或其實現的任何接口。因此,String可以鑄造爲StringObject; HashMap可以被鑄造爲HashMapAbstractMapMapObject

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

Java docs on inheritance是相當不錯的,只是在這裏檢討。

1

這是因爲LocationType不是MyLocationType的實例它是它的父親。例如,如果您向MyLocationType添加了新方法而不是LocationType,然後將LocationType轉換爲MyLocationType如果調用這些新方法,並且LocationType中不存在這些新方法,那麼預期會發生什麼?

MyLocationTypeis aLocationType但是LocationType不是MyLocationType

1

由於MyLocationTypeLocationType類型的,並且可以被轉換爲一個,但LocationTypeMyLocationType和爲此不能轉換到它。

0

因爲你想情況下,參考是 MyLocationType

該樣本的實例總是幫我覺得發生了什麼。

Object o = new Object(); 

    String s = (String) o; 

雖然String一個對象,這並不意味着每一個對象是一個字符串(或在這種情況下,認爲「鑄造」對象是一個字符串)

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); 
    } 
}