CodeGym /Java Blogu /Rastgele /Referans türlerinin genişletilmesi ve daraltılması
John Squirrels
Seviye
San Francisco

Referans türlerinin genişletilmesi ve daraltılması

grupta yayınlandı
MERHABA! Geçmiş bir derste, ilkel tiplerin dökümünü tartışmıştık. Neler tartışıldığını kısaca hatırlayalım. Referans türlerinin genişletilmesi ve daraltılması - 1İ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.

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. intBir değişkene a koymaya çalışırsak short, işler bizim için o kadar düzgün gitmez. Sonuçta, shortdeğişken yalnızca 16 bit bilgi tutar, ancak a int32 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 shortdeğ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 Catdiğerine Doggeç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? introduceSınıfın yöntemi mi Petyoksa 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 Petreferansı genişlettik ve onu bir Animaldeğ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ı WildAnimalve şimdi Coyotemiras 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. Referans türlerinin genişletilmesi ve daraltılması - 2Daha ilginç başka bir örneği ele alalım:

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 Animalve 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 petyalnızca Evcil Hayvanları (ve onların soyundan gelenleri) depolamak için uygundur, herhangi bir hayvan türü için uygun değildir. Bu nedenle, ClassCastExceptionsı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. PetBir değişken tarafından başvurulan bir nesnemiz var Pet. Daha sonra, Animalaynı nesneye işaret eden bir referans. animalBundan 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.
Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION