Giriş
Java
- bir sınıfı bir arayüze cast etmeye
- veya bir arayüzü bir sınıfa cast etmeye
derleme esnasında izin veriyor ve hata olsa bile derleme hatası vermiyor. Aslında derleme esnasında hata yakalamaması gıcık bir şey.
Derleme Hatası Yoksa Bile Halen ClassCastException Fırlatılır
Elimizde şöyle bir kod olsun. Bu kod derlense bile çalışma esnasında halen ClassCastException fırlatır.
Bu mümkün ve açıklaması şöyle.
Örnek
Elimizde şöyle bir kod olsun.
Örnek
Şöyle yaparız. Burada sınıf arayüze cast ediliyor. Derleyici bu cast'lerde hata olsa bile yakalamaz. Ancak sınıf bir başka sınıfa cast edilirse bunu yakalar.
Eğer nesne final ise derleyici nesneyi bir arayüze çevirirken gerekli kontrolleri yapar. Elimizde şöyle bir kod olsun.
Java
- bir sınıfı bir arayüze cast etmeye
- veya bir arayüzü bir sınıfa cast etmeye
derleme esnasında izin veriyor ve hata olsa bile derleme hatası vermiyor. Aslında derleme esnasında hata yakalamaması gıcık bir şey.
Derleme Hatası Yoksa Bile Halen ClassCastException Fırlatılır
Elimizde şöyle bir kod olsun. Bu kod derlense bile çalışma esnasında halen ClassCastException fırlatır.
List<String> strList = new ArrayList<>();
Date d = (Date) strList;
1. Arayüzü Sınıfa Cast Etmek Neden LazımBu mümkün ve açıklaması şöyle.
"A narrowing reference conversion exists from reference type S to reference type T if all of the following are true:"Sınıflar bazen hem bir ata sınıftan kalıtırlar hem de bir veya daha çok arayüzü gerçekleştirirler ve bu nesne kodda arayüz olarak kullanılır. Dolayısıyla arayüzü sınıfa cast etme ihtiyacı doğar.
...
5) "S is an interface type, T is a class type, and T does not name a final class."
Örnek
Elimizde şöyle bir kod olsun.
public class SneakyListDate extends Date implements List<Foo> {
...
}
Şöyle yaparız. Burada arayüz gerçek sınıfa cast ediliyor.List<Foo> list = new SneakyListDate();
Date date = (Date) list; // This one is valid, compiles and runs just fine
2. Sınıfı Arayüze Cast EtmeÖrnek
Şöyle yaparız. Burada sınıf arayüze cast ediliyor. Derleyici bu cast'lerde hata olsa bile yakalamaz. Ancak sınıf bir başka sınıfa cast edilirse bunu yakalar.
public class Foo {
public List<String> getCollectionCast() {
return (List<String>) this; // No compiler error
}
public Map<String, String> getCollection2Cast() {
return (Map<String, String>) this; // No compiler error
}
public Other getCast() {
return (Other)this; // Incompatible types. Cannot cast Foo to Other
}
public static class Other {
// Just for casting demo
}
}
Açıklaması şöyle. Çünkü Foo'dan kalıtan bir sınıf List arayüzünden de kalıtabilir. Bu durumda getCollection() metodunu doğru hale gelir.It's not because they're collection classes, it's because they're interfaces. Foo doesn't implement them, but subclasses of it could. So it's not a compile-time error, since those methods may be valid for subclasses. At runtime, if this isn't of a class that implements those interfaces, naturally it's a runtime error.Örnek
If you change List<String> to ArrayList<String>, you'll get a compiler-time error for that, too, since a Foo subclass could implement List, but can't extend ArrayList (since Foo doesn't). Similarly, if you make Foo final, the compiler will give you an error for your interface casts because it knows they can never be true (since Foo can't have subclasses, and doesn't implement those interfaces).
Eğer nesne final ise derleyici nesneyi bir arayüze çevirirken gerekli kontrolleri yapar. Elimizde şöyle bir kod olsun.
interface I1 { }
interface I2 { }
class C1 implements I1 { }
class C2 implements I2 { }
public class Test{
public static void main(){
C1 o1 = new C1();
C2 o2 = new C2();
Integer o3 = new Integer(4);
I2 x = (I2)o1; //compiler does not complain
I2 y = (I2)o3; //compiler complains here !!
}
}
Açıklaması şöyle. Burada Integer'dan kalıtan bir başka sınıf olmadığını derleyici biliyor. Dolayısıyla I2'den kalıtma ihtimali yok.The Integer class is final, so o3 cannot be an instance of a subclass of Integer
Hiç yorum yok:
Yorum Gönder