JavaRush /Blog Java /Random-MS /Autoboxing dan unboxing dalam Java

Autoboxing dan unboxing dalam Java

Diterbitkan dalam kumpulan
<h2>Pengenalan</h2>Bahasa pengaturcaraan, seperti bahasa yang dituturkan orang, kehidupan dan perubahan, fenomena baharu muncul di dalamnya untuk menjadikan bahasa itu lebih mudah digunakan. Dan seperti yang kita tahu, bahasa harus dengan mudah menyatakan fikiran kita.
Autoboxing dan unboxing dalam Java - 1
Jadi, dalam Java SE 5, mekanisme tinju/nyah kotak diperkenalkan. Dan tutorial berasingan daripada Oracle dikhaskan untuk ciri-ciri cara ini untuk meluahkan fikiran: Autoboxing dan Unboxing . <h2>Tinju pembungkusan automatik</h2>Mari lihat contoh Tinju pembungkusan automatik. Pertama, mari kita lihat bagaimana ia berfungsi. Mari gunakan laman web compilejava.net dan buat kelas:
public class App {
    public static void main(String[] args) {
        Integer portNumber = 8080;
        if (args.length != 0) {
            portNumber = Integer.valueOf(args[0]);
        }
        System.out.println("Port number is: " + portNumber);
    }
}
Kod mudah. Kita boleh menentukan parameter input dan menukar nilai port. Seperti yang kita lihat, kerana kita membaca nilai port daripada Stringparameter, kita mendapatkannya Integerdengan mendapatkannya melalui Integer.valueOf. Oleh itu, kami terpaksa menentukannya bukan sebagai jenis primitif, tetapi sebagai jenis objek Integer. Dan di sini kita mendapat, dalam satu tangan, kita mempunyai pembolehubah objek, dan nilai lalai adalah primitif. Dan ia berfungsi. Tetapi kita tidak percaya pada sihir, bukan? Mari kita lihat "di bawah tudung," seperti yang mereka katakan. Muat turun kod sumber daripada compilejava.net dengan mengklik "Muat turun ZIP". Selepas itu, ekstrak arkib yang dimuat turun ke dalam direktori dan pergi ke sana. Sekarang mari kita lakukan: javap -c -p App.classdi mana App.class ialah fail kelas yang disusun untuk kelas anda. Kami akan melihat kandungan seperti ini:
Autoboxing dan unboxing dalam Java - 2
Ini adalah "kod bait" terkenal yang sama. Tetapi apa yang penting bagi kita sekarang ialah apa yang kita lihat. Pertama, primitif 8080 diletakkan pada timbunan pelaksanaan kaedah, dan kemudian Integer.valueOf dilaksanakan . Ini adalah "keajaiban" tinju. Dan di dalam sihir kelihatan seperti ini:
Autoboxing dan unboxing dalam Java - 3
Iaitu, pada dasarnya, yang baru akan diambil Integeratau akan diperoleh Integerdaripada cache (cache tidak lebih daripada sekadar tatasusunan Integer) bergantung pada nilai nombor. Sememangnya, Integerbukan seorang sahaja yang bertuah. Terdapat senarai keseluruhan jenis primitif yang berkaitan dan pembungkusnya (kelas yang mewakili primitif dalam dunia OOP). Senarai ini diberikan di bahagian paling bawah Tutorial dari Oracle: " Autoboxing dan Unboxing ". Perlu diperhatikan dengan segera bahawa tatasusunan yang dibuat daripada primitif tidak mempunyai "pembungkus" tanpa menyambungkan mana-mana perpustakaan pihak ketiga. Itu. Arrays.asListtidak akan membuat daripada int[]untuk kita Listdaripada Integer's. <h2>Nyah kotak</h2>Proses terbalik kepada tinju dipanggil nyah kotak. Mari lihat contoh pembongkaran:
public class App {

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Please, enter params");
            return;
        }
      	int value = Math.abs(Integer.valueOf(args[0]));
        System.out.println("Absolute value is: " + value);
    }

}
Math.abshanya menerima yang primitif. Apa nak buat? Kelas pembalut mempunyai kaedah khas untuk kes ini yang mengembalikan primitif. Sebagai contoh, ini ialah Integerkaedah intValue . Jika kita melihat bytecode, ia adalah seperti ini:
Autoboxing dan unboxing dalam Java - 4
Rupa-rupanya, tiada sihir. Semuanya dalam Java. Ia hanya berfungsi "dengan sendirinya". Untuk kemudahan kami. <h2>Mengarut</h2>
Autoboxing dan unboxing dalam Java - 5
Mana-mana alat, jika digunakan secara tidak betul, menjadi senjata yang menggerunkan terhadap dirinya sendiri. Dan mekanisme tinju/nyahbox automatik di Jawa tidak terkecuali. Perbandingan pertama yang jelas adalah melalui ==. Saya rasa ini jelas, tetapi mari kita lihat semula:
public static void main(String[] args) {
    Integer inCacheValue = 127;
    Integer inCacheValue2 = 127;
    Integer notInCache = 128; // new Integer(129)
    Integer notInCache2 = 128; // new Integer(129)
    System.out.println(inCacheValue == inCacheValue2); //true
    System.out.println(notInCache == notInCache2); //false
}
Dalam kes pertama, nilai diambil daripada Integercache nilai (lihat penjelasan Boxing di atas), dan dalam kes kedua objek baharu akan dibuat setiap kali. Tetapi di sini adalah berbaloi untuk membuat tempahan. Tingkah laku ini bergantung pada sempadan tinggi cache ( java.lang.Integer.IntegerCache.high ). Selain itu, had ini mungkin berubah disebabkan oleh tetapan lain. Anda boleh membaca perbincangan mengenai topik ini pada stackoverflow: Berapa besar cache Integer? Sememangnya, objek perlu dibandingkan menggunakan sama: System.out.println(notInCache.equals(notInCache2)); Masalah kedua yang dikaitkan dengan mekanisme yang sama ialah prestasi. Mana-mana tinju di Jawa adalah bersamaan dengan mencipta objek baharu. Jika nombor itu tidak termasuk dalam nilai cache (iaitu -128 hingga 127), maka objek baharu akan dibuat setiap kali. Jika tiba-tiba pembungkusan (iaitu tinju) dilakukan dalam gelung, ini akan menyebabkan peningkatan besar dalam objek yang tidak perlu dan penggunaan sumber untuk kerja pemungut sampah. Oleh itu, jangan terlalu melulu mengenainya. Satu rake ketiga, tidak kurang menyakitkan berpunca daripada mekanisme yang sama:
public static void check(Integer value) {
    if (value <= 0) {
        throw new IllegalStateException("Value is too small");
    }
}
Dalam kod ini, orang itu jelas cuba untuk tidak melepasi ralat. Tetapi tiada pemeriksaan untuk null. Jika ia datang kepada input null, maka bukannya ralat yang boleh difahami, kita akan mendapat ralat yang tidak dapat difahami NullPointerException. Kerana sebagai perbandingan, Java akan cuba untuk melaksanakan value.intValuedan ranap, kerana... valueakan null. <h2>Kesimpulan</h2>Mekanisme tinju/nyah kotak membolehkan pengaturcara menulis kod yang lebih sedikit dan kadangkala tidak memikirkan tentang menukar daripada primitif kepada objek dan belakang. Tetapi itu tidak bermakna anda harus melupakan cara ia berfungsi. Jika tidak, anda mungkin membuat kesilapan yang mungkin tidak muncul serta-merta. Kita tidak seharusnya bergantung pada bahagian sistem yang tidak sepenuhnya di bawah kawalan kita (seperti sempadan integer). Tetapi jangan lupa tentang semua kelebihan kelas pembalut (seperti Integer). Selalunya kelas pembalut ini mempunyai satu set kaedah statik tambahan yang akan menjadikan hidup anda lebih baik dan kod anda lebih ekspresif. Berikut ialah contoh tangkapan:
public static void main(String[] args) {
    int first = 1;
    int second = 5;
    System.out.println(Integer.max(first, second));
    System.out.println(Character.toLowerCase('S'));
}
Kesimpulan yang betul dari segala-galanya ialah tidak ada sihir, ada semacam kesedaran. Dan tidak semuanya akan sentiasa seperti yang kita harapkan. Sebagai contoh, tiada pembungkusan: System.out.println("The number is " + 8); Contoh di atas akan dioptimumkan oleh pengkompil ke dalam satu baris. Iaitu, seolah-olah anda menulis "Nombornya ialah 8". Dan dalam contoh di bawah tidak akan ada pembungkusan sama ada:
public static void main(String[] args) {
    System.out.println("The number is " + Math.abs(-2));
}
Bagaimana mungkin apabila kita printlnmengambil objek sebagai input dan perlu menyambungkan talian. Garisan... ya, sebab itu tiada pembungkusan seperti itu. Terdapat Integerkaedah statik, tetapi sebahagian daripadanya adalah package. Iaitu, kita tidak boleh menggunakannya, tetapi dalam Java sendiri mereka boleh digunakan secara aktif. Ini betul-betul berlaku di sini. Kaedah getChars akan dipanggil, yang membuat susunan aksara daripada nombor tersebut. Sekali lagi, tiada sihir, hanya Java). Jadi dalam apa-apa keadaan yang tidak jelas, anda hanya perlu melihat pelaksanaan dan sekurang-kurangnya sesuatu akan jatuh ke tempatnya. #Viacheslav
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION