1. 程式人生 > >關於java中父類和子類轉型的問題java.lang.ClassCastException

關於java中父類和子類轉型的問題java.lang.ClassCastException

我們都知道,java是面向物件的語言,繼承是其一個很重要的特性,看下面這段程式碼:

package my.java.test;
class FatherClass {
    int fatherField;
void fatherMethod() {
        System.out.println("這是父類的方法");
}
}
package my.java.test;
public class ChildClass extends FatherClass {
    int childField;
void childMethod() {
        System.out.println("
這是子類的方法"); } public static void main(String[] args) { FatherClass fatherClass = new ChildClass(); fatherClass.fatherMethod(); } }

這沒有任何的問題,這是屬於java的多型,子類自動的向上轉型成父類,使用父類的引用來指向子類的實列,從而導致在使用上拋棄的子類特有的屬性和方法,那麼我們再看下面一段程式碼:

package my.java.test;
public class ChildClass extends FatherClass {
    int 
childField; void childMethod() { System.out.println("這是子類的方法"); } public static void main(String[] args) { FatherClass fatherClass = new FatherClass(); ChildClass childClass = (ChildClass) fatherClass; childClass.childMethod(); } }

這段程式碼編譯可以通過,但是執行的時候回丟擲java.lang.ClassCastException,我們來想想,為什麼?

  首先我們在父類和子類分別定義了成員變數和方法,我們我們知道,在我們new任何一個物件的時候,都會在堆記憶體中申請空間去存放這個物件的屬性資訊,那麼我們這裡new了一個FatherClass的實列,那麼在堆記憶體中fatherFiled這個成員變數會存在於物件的空間裡面.

  那麼當我們要把這物件強制轉型成子類的時候,假如我們可以轉型成功,那麼我們是不是可以用這個指向了父類實列物件的子類引用去引用子類特有的成員變數childField,那麼問題來了,當在new一個父類的實列物件的時候,根本就沒有在父類的物件空間裡面為childField變數分配空間,因為父類根本沒有這個變數,那麼何以引用呢?所以這也是為什麼會報錯的原因了!

我們再看下面這種情況:

package my.java.test;
public class ChildClass extends FatherClass {
    int childField;
void childMethod() {
        System.out.println("這是子類的方法");
}

    public static void main(String[] args) {
        FatherClass fatherClass = new ChildClass();
ChildClass childClass = (ChildClass) fatherClass;
childClass.childMethod();
}
}

這段程式碼是可以執行的,那麼這時候就會有讀者納悶了,,剛剛不還說的好好的,父類不能強制轉型成子類嗎?不過你有沒有發現,在我們申請例項物件的時候,我們new的是ChildClass,然後利用物件的多型轉型成父類,然後我們又重新強制轉型成子類,如果讀者理解了我前面解釋的情況,那麼應該可以明白這裡為什麼不會報錯的原因了.

  這也是很多java程式碼和Android程式碼中,用父類強制轉型成子類不會報錯,而你自己去寫一個父類轉型成子類卻不行的原因了,如果你去看他們的原始碼,你會發現,其實原始碼的內部在new物件的時候,是生成的子類物件,然後直接向上轉型成了父類.