JavaRush /Blog Java /Random-MS /Pengembangan dan pengecutan jenis rujukan

Pengembangan dan pengecutan jenis rujukan

Diterbitkan dalam kumpulan
hello! Dalam salah satu kuliah sebelumnya, kami membincangkan pemutus jenis primitif. Mari kita ingat secara ringkas apa yang kita bincangkan. Pengembangan dan pengecutan jenis rujukan - 1Kami mewakili jenis primitif (dalam kes ini, angka) sebagai anak patung bersarang mengikut jumlah memori yang didudukinya. Seperti yang anda ingat, meletakkan anak patung bersarang yang lebih kecil ke dalam yang lebih besar akan menjadi mudah dalam kehidupan sebenar dan dalam pengaturcaraan Java.
public class Main {
   public static void main(String[] args) {
        short smallNumber = 100;
        int bigNumber =  smallNumber;
        System.out.println(bigNumber);
   }
}
Ini ialah contoh penukaran automatik atau sambungan . Ia berlaku dengan sendirinya, jadi tidak perlu menulis kod tambahan. Pada akhirnya, kami tidak melakukan apa-apa yang luar biasa: kami hanya meletakkan anak patung bersarang yang lebih kecil ke dalam anak patung bersarang yang lebih besar. Perkara lain jika kita cuba melakukan sebaliknya dan meletakkan anak patung matryoshka yang besar ke dalam yang lebih kecil. Ini tidak boleh dilakukan dalam kehidupan, tetapi dalam pengaturcaraan ia boleh dilakukan. Tetapi ada satu kaveat. Jika kita cuba meletakkan nilai intke dalam pembolehubah short, ia tidak akan berjaya dengan mudah. Lagipun, hanya 16 bit maklumat boleh dimuatkan ke dalam pembolehubah short, tetapi nilainya intmengambil masa 32 bit! Akibatnya, nilai yang dihantar akan diherotkan. Pengkompil akan memberi kami ralat (“ kawan, anda sedang melakukan sesuatu yang mencurigakan! ”), tetapi jika kami menyatakan secara jelas jenis yang kami hantarkan nilai kami, ia masih akan melaksanakan operasi sedemikian.
public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       bigNumber = (short) bigNumber;

       System.out.println(bigNumber);

   }

}
Dalam contoh di atas, kami melakukan perkara itu. Operasi telah selesai, tetapi kerana shorthanya 16 daripada 32 bit masuk ke dalam pembolehubah, nilai akhir telah diherotkan, dan akibatnya kami menerima nombor -27008 . Operasi ini dipanggil penukaran eksplisit, atau penyempitan .

Contoh lanjutan dan pengecutan jenis rujukan

Sekarang kita akan bercakap tentang operasi yang sama, tetapi tidak terpakai untuk jenis primitif, tetapi untuk objek dan pembolehubah rujukan ! Bagaimanakah ini berfungsi di Jawa? Cukup mudah sebenarnya. Terdapat objek yang tidak berkaitan antara satu sama lain. Adalah logik untuk menganggap bahawa mereka tidak boleh ditukar kepada satu sama lain sama ada secara eksplisit atau automatik:
public class Cat {
}

public class Dog {
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Dog();//error!

   }

}
Di sini kita, sudah tentu, akan mendapat ralat. Kelas Cattidak Dogberkaitan antara satu sama lain, dan kami belum menulis "penukar" dari satu sama lain. Adalah logik bahawa kita tidak akan dapat melakukan ini: pengkompil tidak tahu cara menukar objek ini antara satu sama lain. Perkara lain jika objek disambungkan antara satu sama lain! Bagaimana? Pertama sekali, menggunakan warisan. Mari cuba buat sistem kelas kecil dengan warisan. Kami akan mempunyai kelas umum yang mewakili haiwan:
public class Animal {

   public void introduce() {

       System.out.println("i'm Animal");
   }
}
Haiwan, seperti yang anda ketahui, adalah domestik dan liar:
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");
   }
}
Sebagai contoh, mari kita ambil anjing - anjing domestik dan anjing hutan:
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");
   }
}
Kelas kami sengaja menjadi yang paling primitif untuk menjadikannya lebih mudah untuk dilihat. Kami tidak benar-benar memerlukan medan di sini, dan satu kaedah sudah memadai. Mari cuba jalankan kod berikut:
public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
Apa yang anda fikir akan dikeluarkan kepada konsol? Adakah kaedah introducekelas Petatau kelas akan berfungsi Animal? Cuba untuk membenarkan jawapan anda sebelum meneruskan pembacaan. Dan inilah hasilnya! i'm Pet Mengapa jawapannya menjadi begini? Mudah sahaja. Kami mempunyai pembolehubah induk dan objek kanak-kanak. Dengan menulis:
Animal animal = new Pet();
Kami telah melanjutkan jenis rujukanPet dan menyimpan objeknya dalam pembolehubah Animal. Seperti jenis primitif, lanjutan jenis rujukan dalam Java dilakukan secara automatik. Tidak perlu menulis kod tambahan untuk ini. Sekarang kita mempunyai objek kanak-kanak yang dilampirkan pada rujukan ibu bapa, dan sebagai hasilnya kita melihat bahawa kaedah itu dipanggil pada kelas kanak-kanak. Jika anda masih tidak memahami sepenuhnya mengapa kod ini berfungsi, tulis semula dalam bahasa mudah:
Животное животное = new ДомашнееЖивотное();
Tidak ada masalah dengan itu, bukan? Bayangkan ini adalah kehidupan sebenar, dan pautan dalam kes ini ialah tag kertas ringkas yang menyatakan "Haiwan." Jika anda mengambil sekeping kertas dan melampirkannya pada kolar mana-mana haiwan peliharaan, semuanya akan baik-baik saja. Mana-mana haiwan peliharaan tetap haiwan! Proses sebaliknya, iaitu memindahkan pokok pusaka kepada ahli waris, adalah penyempitan:
public class Main {

   public static void main(String[] args) {

       WildAnimal wildAnimal = new Coyote();

       Coyote coyote = (Coyote) wildAnimal;

       coyote.introduce();
   }
}
Seperti yang anda boleh lihat, di sini kami secara eksplisit menunjukkan kelas mana kami ingin menghantar objek kami. Sebelum ini kita mempunyai pembolehubah WildAnimal, dan sekarang Coyote, yang turun ke pokok warisan. Adalah logik bahawa pengkompil tidak akan melangkau operasi sedemikian tanpa petunjuk yang jelas, tetapi jika anda menentukan jenis dalam kurungan, semuanya akan berfungsi. Pengembangan dan pengecutan jenis rujukan - 2 Mari lihat contoh lain, lebih menarik:
public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal();//error!
   }
}
Pengkompil melemparkan ralat! Apakah sebabnya? Hakikatnya ialah anda cuba menetapkan objek induk kepada pembolehubah anak. Dengan kata lain, anda ingin melakukan ini:
ДомашнееЖивотное домашнееЖивотное = new Животное();
Tetapi mungkin jika kita secara jelas menunjukkan jenis yang kita cuba lakukan, kita akan berjaya? Nombor itu nampaknya berkesan, mari cuba! :)
public class Main {

   public static void main(String[] args) {

       Pet pet = (Pet) new Animal();
   }
}
Pengecualian dalam benang "utama" java.lang.ClassCastException: Haiwan tidak boleh dihantar ke Ralat Binatang! Penyusun tidak mengadu kali ini, tetapi akibatnya kami menerima pengecualian. Kami sudah tahu sebabnya: kami cuba menetapkan objek induk kepada pembolehubah anak. Mengapa, sebenarnya, ini tidak boleh dilakukan? Kerana tidak semua Haiwan adalah Haiwan. Anda mencipta objek Animaldan cuba menetapkannya kepada pembolehubah Pet. Tetapi, sebagai contoh, anjing hutan juga Animal, tetapi ia bukan Pet, haiwan domestik. Dengan kata lain, apabila anda menulis:
Pet pet = (Pet) new Animal();
new Animal()Mana-mana haiwan boleh berada di sana , dan ia tidak semestinya domestik! Sememangnya, pembolehubah anda Pet pethanya sesuai untuk menyimpan haiwan peliharaan (dan keturunannya), dan bukan untuk semua orang. Oleh itu, untuk kes sedemikian, pengecualian khas telah dibuat di Jawa - ClassCastExceptionralat semasa menghantar kelas. Mari sebut sekali lagi untuk menjadikannya lebih jelas. Pembolehubah induk (rujukan) boleh menunjuk kepada objek kelas keturunan:
public class Main {

   public static void main(String[] args) {

       Pet pet =  new Pet();
       Animal animal = pet;

       Pet pet2 = (Pet) animal;
       pet2.introduce();
   }
}
Sebagai contoh, kami tidak akan menghadapi sebarang masalah di sini. Kami mempunyai objek Petyang ditunjuk oleh pautan Pet. Kemudian pautan baru mula menghala ke objek yang sama Animal. Selepas itu kami melakukan penukaran animalkepada Pet. Kenapa kita buat ini, by the way? Kali terakhir kami mendapat pengecualian! Kerana kali ini objek asal kita ialah Pet pet!
Pet pet =  new Pet();
Dan dalam contoh sebelumnya ia adalah objek Animal:
Pet pet = (Pet) new Animal();
Pembolehubah turunan tidak boleh diberikan objek moyang. Sebaliknya, anda boleh melakukannya.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION