MERHABA! Geçmiş bir derste, ilkel tiplerin dökümünü tartışmıştık. Neler tartışıldığını kısaca hatırlayalım.
İlkel türleri (bu örnekte sayısal türleri), işgal ettikleri bellek miktarına göre boyutları değişen, yuvalanmış bebekler olarak hayal ettik. Hatırlayacağınız gibi, daha büyük bir bebeğin içine daha küçük bir oyuncak bebek koymak hem gerçek hayatta hem de Java programlamada basittir.
Daha ilginç başka bir örneği ele alalım:

public class Main {
public static void main(String[] args) {
int bigNumber = 10000000;
short smallNumber = (short) bigNumber;
System.out.println(smallNumber);
}
}
Bu, otomatik dönüştürme veya genişletmeye bir örnektir . Kendi kendine olur, bu nedenle ek kod yazmanıza gerek yoktur. Sonunda, alışılmadık bir şey yapmıyoruz: sadece daha küçük bir bebeği daha büyük bir bebeğe koyuyoruz. Tersini yapmaya çalışıp daha büyük bir Rus bebeğini daha küçük bir bebeğe koymamız başka bir mesele. Bunu gerçek hayatta yapamazsınız ama programlamada yapabilirsiniz. Ama bir nüans var. int
Bir değişkene a koymaya çalışırsak short
, işler bizim için o kadar düzgün gitmez. Sonuçta, short
değişken yalnızca 16 bit bilgi tutar, ancak a int
32 bit yer kaplar! Sonuç olarak, geçirilen değer bozulur. Derleyici bize bir hata verecektir (' Dostum, şüpheli bir şey yapıyorsun!'). Ancak, değerimizi dönüştürdüğümüz türü açıkça belirtirsek, devam edecek ve işlemi gerçekleştirecektir.
public class Main {
public static void main(String[] args) {
int bigNumber = 10000000;
bigNumber = (short) bigNumber;
System.out.println(bigNumber);
}
}
Yukarıdaki örnekte yaptığımız şey buydu. İşlem gerçekleştirildi, ancak short
değişken 32 baytın yalnızca 16'sını barındırabildiği için son değer bozuluyor ve -27008 sayısını alıyoruz . Böyle bir işleme, açık dönüştürme veya daraltma denir .
Referans türlerinin genişletilmesi ve daraltılmasına ilişkin örnekler
Şimdi ilkel türlere değil, nesnelere ve referans değişkenlere uygulanan aynı operatörlerden bahsedelim ! Java'da bu nasıl çalışır? Aslında oldukça basit. İlişkisiz nesneler var. Açıkça veya otomatik olarak birbirlerine dönüştürülemeyeceklerini varsaymak mantıklı olacaktır:
public class Cat {
}
public class Dog {
}
public class Main {
public static void main(String[] args) {
Cat cat = new Dog(); // Error!
}
}
Burada tabii ki bir hata alıyoruz. ve sınıfları birbiriyle ilişkili değildir ve birinden Cat
diğerine Dog
geçmek için bir 'dönüştürücü' yazmadık. Bunu yapamayacağımız mantıklı: derleyicinin bu nesneleri bir türden diğerine nasıl dönüştüreceği hakkında hiçbir fikri yok. Nesneler birbiriyle ilişkiliyse, o başka bir konu! Nasıl ilgili? Her şeyden önce, miras yoluyla. Küçük bir sınıf sistemi oluşturmak için kalıtımı kullanmayı deneyelim. Hayvanları temsil edecek ortak bir sınıfımız olacak:
public class Animal {
public void introduce() {
System.out.println("I'm Animal");
}
}
Hayvanların evcilleştirilebileceğini (evcil hayvan) veya vahşi olabileceğini herkes bilir:
public class WildAnimal extends Animal {
public void introduce() {
System.out.println("I'm WildAnimal");
}
}
public class Pet extends Animal {
public void introduce() {
System.out.println("I'm Pet");
}
}
Örneğin, köpekleri ele alalım - evcil köpeklerimiz ve çakallarımız var:
public class Dog extends Pet {
public void introduce() {
System.out.println("I'm Dog");
}
}
public class Coyote extends WildAnimal {
public void introduce() {
System.out.println ("I'm Coyote");
}
}
Anlaşılmalarını kolaylaştırmak için en temel sınıfları özellikle seçtik. Gerçekten herhangi bir alana ihtiyacımız yok ve bir yöntem yeterli. Bu kodu çalıştırmayı deneyelim:
public class Main {
public static void main(String[] args) {
Animal animal = new Pet();
animal.introduce();
}
}
Sizce konsolda ne gösterilecek? introduce
Sınıfın yöntemi mi Pet
yoksa sınıfın yöntemi mi Animal
çağrılacak? Okumaya devam etmeden önce cevabınızı doğrulamaya çalışın. Ve işte sonuç! Ben Pet'im Bunu neden aldık? Her şey basit. Bir üst değişkenimiz ve bir alt nesnemiz var. Yazarak,
Animal animal = new Pet();
bir Pet
referansı genişlettik ve onu bir Animal
değişkene atadık. İlkel türlerde olduğu gibi, başvuru türleri de Java'da otomatik olarak genişletilir. Bunun gerçekleşmesi için ek kod yazmanıza gerek yoktur. Artık bir üst referansa atanmış bir alt nesnemiz var. Sonuç olarak, method çağrısının elde edilen sınıf üzerinde yapıldığını görüyoruz. Bu kodun neden çalıştığını hala tam olarak anlamadıysanız, düz bir dille yeniden yazın:
Animal animal = new DomesticatedAnimal();
Bunda bir sorun yok, değil mi? Bunun gerçek hayat olduğunu ve referansın, üzerinde 'Hayvan' yazan bir kağıt etiket olduğunu hayal edin. O kağıdı alıp herhangi bir evcil hayvanın tasmasına takarsanız, her şey doğru olacaktır. Sonuçta, herhangi bir evcil hayvan bir hayvandır! Tersi süreç - miras ağacından torunlara doğru ilerlemek - daralmaktadır:
public class Main {
public static void main(String[] args) {
WildAnimal wildAnimal = new Coyote();
Coyote coyote = (Coyote) wildAnimal;
coyote.introduce();
}
}
Gördüğünüz gibi, burada nesnemizi dönüştürmek istediğimiz sınıfı açıkça belirtiyoruz. Daha önce bir değişkenimiz vardı WildAnimal
ve şimdi Coyote
miras ağacında daha düşük olan bir değişkenimiz var. Açık bir gösterge olmadan derleyicinin böyle bir işleme izin vermemesi mantıklıdır, ancak türü parantez içinde belirtirsek, o zaman her şey çalışır. 
public class Main {
public static void main(String[] args) {
Pet pet = new Animal(); // Error!
}
}
Derleyici bir hata üretir! Ama neden? Çünkü bir alt öğe referansına bir üst nesne atamaya çalışıyorsunuz. Başka bir deyişle, şöyle bir şey yapmaya çalışıyorsunuz:
DomesticatedAnimal domesticatedAnimal = new Animal();
Peki, dönüştürmeye çalıştığımız türü açıkça belirtirsek belki her şey işe yarar? Sayılarla işe yaradı - Hadi bir deneyelim! :)
public class Main {
public static void main(String[] args) {
Pet pet = (Pet) new Animal();
}
}
"main" ileti dizisinde istisna java.lang.ClassCastException: Animal, Pet Error'a aktarılamaz ! Derleyici bu sefer bize bağırmadı ama sonunda bir istisnayla karşılaştık. Sebebini zaten biliyoruz: bir alt öğe referansına bir üst nesne atamaya çalışıyoruz. Ama neden tam olarak bunu yapamıyorsun? Çünkü tüm Hayvanlar Evcilleştirilmiş Hayvanlar değildir. Bir nesne yarattınız Animal
ve onu bir değişkene atamaya çalışıyorsunuz Pet
. Bir çakal da bir Animal
, ama bir değil Pet
. Başka bir deyişle, yazarken
Pet pet = (Pet) new Animal();
new Animal()
herhangi bir hayvanı temsil edebilir, mutlaka bir evcil hayvan değil! Doğal olarak, değişkeniniz Pet pet
yalnızca Evcil Hayvanları (ve onların soyundan gelenleri) depolamak için uygundur, herhangi bir hayvan türü için uygun değildir. Bu nedenle, ClassCastException
sınıfları yayınlarken bir hatanın oluştuğu durumlar için özel bir Java istisnası yaratılmıştır. İşleri daha net hale getirmek için tekrar gözden geçirelim. Bir ebeveyn referansı, bir alt sınıfın örneklerine işaret edebilir:
public class Main {
public static void main(String[] args) {
Pet pet = new Pet();
Animal animal = pet;
Pet pet2 = (Pet) animal;
pet2.introduce();
}
}
Örneğin, burada hiçbir sorunumuz yok. Pet
Bir değişken tarafından başvurulan bir nesnemiz var Pet
. Daha sonra, Animal
aynı nesneye işaret eden bir referans. animal
Bundan sonra a'ya dönüştürüyoruz Pet
. Bu arada, bu bizim için neden işe yaradı? Geçen sefer bir istisnamız oldu! Çünkü bu sefer orijinal nesnemiz bir Pet
!
Pet pet = new Pet();
Ancak son örnekte, bu bir nesneydi Animal
:
Pet pet = (Pet) new Animal();
Bir alt değişkene bir üst nesne atayamazsınız. Tam tersini yapabilirsiniz.
Daha fazla okuma: |
---|
GO TO FULL VERSION