Menguraikan jawaban yang diberikan oleh Michael Berry.
Dog d = (Dog)Animal; //Compiles but fails at runtime
Di sini Anda mengatakan kepada kompiler "Percayalah. Saya tahu d
benar-benar mengacu pada Dog
objek" meskipun tidak.
Ingat kompiler dipaksa untuk mempercayai kami ketika kami melakukan downcast .
Kompilator hanya tahu tentang tipe referensi yang dideklarasikan. JVM saat runtime tahu apa objek sebenarnya.
Jadi ketika JVM pada saat runtime mengetahui bahwa Dog d
sebenarnya mengacu pada Animal
dan bukan Dog
objek yang dikatakannya. Hei ... kau berbohong ke kompiler dan membuang banyak lemak ClassCastException
.
Jadi, jika Anda downcasting Anda harus menggunakan instanceof
tes untuk menghindari mengacaukan.
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
}
Sekarang sebuah pertanyaan muncul di benak kami. Mengapa kompiler itu membiarkan yang tertunduk ketika akhirnya akan membuang java.lang.ClassCastException
?
Jawabannya adalah yang dapat dilakukan oleh semua kompiler adalah memverifikasi bahwa kedua jenis berada di pohon warisan yang sama, jadi tergantung pada kode apa pun yang mungkin datang sebelum downcast, mungkin animal
jenisnya dog
.
Kompiler harus mengizinkan hal-hal yang mungkin dapat berfungsi saat runtime.
Pertimbangkan snipet kode berikut:
public static void main(String[] args)
{
Dog d = getMeAnAnimal();// ERROR: Type mismatch: cannot convert Animal to Dog
Dog d = (Dog)getMeAnAnimal(); // Downcast works fine. No ClassCastException :)
d.eat();
}
private static Animal getMeAnAnimal()
{
Animal animal = new Dog();
return animal;
}
Namun, jika kompiler yakin bahwa para pemain tidak akan bekerja, kompilasi akan gagal. IE Jika Anda mencoba untuk melemparkan objek dalam hierarki warisan yang berbeda
String s = (String)d; // ERROR : cannot cast for Dog to String
Tidak seperti downcasting, upcasting bekerja secara implisit karena ketika Anda membuangnya Anda secara implisit membatasi jumlah metode yang dapat Anda gunakan, sebagai kebalikan dari downcasting, yang menyiratkan bahwa di kemudian hari, Anda mungkin ingin menggunakan metode yang lebih spesifik.
Dog d = new Dog();
Animal animal1 = d; // Works fine with no explicit cast
Animal animal2 = (Animal) d; // Works fine with n explicit cast
Kedua hal yang disebutkan di atas akan bekerja dengan baik tanpa kecuali karena Anjing IS-A Animal, anithing an Animal dapat melakukan, seekor anjing dapat melakukannya. Tetapi itu tidak benar vica-versa.