JavaRush /Java Blog /Random-ID /Autoboxing dan unboxing di Java
Viacheslav
Level 3

Autoboxing dan unboxing di Java

Dipublikasikan di grup Random-ID
<h2>Pendahuluan</h2>Bahasa pemrograman, seperti bahasa yang digunakan orang, hidup dan berubah, fenomena baru muncul di dalamnya untuk membuat bahasa tersebut lebih nyaman digunakan. Dan seperti yang kita tahu, bahasa seharusnya bisa mengekspresikan pikiran kita dengan nyaman.
Autoboxing dan unboxing di Java - 1
Jadi, di Java SE 5, mekanisme boxing/unboxing diperkenalkan. Dan tutorial terpisah dari Oracle dikhususkan untuk fitur sarana mengekspresikan pikiran ini: Autoboxing dan Unboxing . <h2>Tinju pengepakan otomatis</h2>Mari kita lihat contoh Tinju pengepakan otomatis. Pertama, mari kita lihat cara kerjanya. Mari gunakan situs kompilasijava.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);
    }
}
Kode sederhana. Kita dapat menentukan parameter input dan mengubah nilai port. Seperti yang bisa kita lihat, karena kita membaca nilai port dari Stringparameter, kita mendapatkannya Integerdengan melewatinya Integer.valueOf. Oleh karena itu, kita terpaksa menentukannya bukan sebagai tipe primitif, tetapi sebagai tipe objek Integer. Dan di sini kita mendapatkan di satu sisi, kita memiliki variabel objek, dan nilai defaultnya adalah primitif. Dan itu berhasil. Tapi kami tidak percaya pada sihir, bukan? Mari kita lihat “di balik terpal”, seperti kata mereka. Unduh kode sumber dari kompilasijava.net dengan mengklik “Unduh ZIP”. Setelah itu, ekstrak arsip yang diunduh ke dalam direktori dan buka. Sekarang mari kita lakukan: javap -c -p App.classdi mana App.class adalah file kelas yang dikompilasi untuk kelas Anda. Kita akan melihat konten seperti ini:
Autoboxing dan unboxing di Java - 2
Ini adalah “bytecode” terkenal yang sama. Namun yang penting bagi kami saat ini adalah apa yang kami lihat. Pertama, primitif 8080 ditempatkan pada tumpukan eksekusi metode, dan kemudian Integer.valueOf dijalankan . Inilah “keajaiban” tinju. Dan di dalam keajaiban itu terlihat seperti ini:
Autoboxing dan unboxing di Java - 3
Artinya, pada intinya, yang baru akan diambil Integeratau akan diperoleh Integerdari cache (cache tidak lebih dari sekedar array Integer) tergantung pada nilai angkanya. Tentu saja, Integertidak hanya satu orang yang seberuntung itu. Ada daftar lengkap tipe primitif terkait dan pembungkusnya (kelas yang mewakili primitif di dunia OOP). Daftar ini diberikan di bagian paling bawah Tutorial dari Oracle: “ Autoboxing dan Unboxing ”. Perlu segera dicatat bahwa array yang dibuat dari primitif tidak memiliki "pembungkus" tanpa menghubungkan perpustakaan pihak ketiga mana pun. Itu. Arrays.asListtidak akan membuat dari int[]untuk kita Listdari Integer's. <h2>Membuka kotak</h2>Proses kebalikan dari membuka kotak disebut unboxing. Mari kita 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 primitif. Apa yang harus dilakukan? Kelas wrapper memiliki metode khusus untuk kasus ini yang mengembalikan primitif. Misalnya, ini adalah Integermetode intValue . Kalau kita lihat bytecode-nya seperti ini:
Autoboxing dan unboxing di Java - 4
Seperti yang Anda lihat, tidak ada keajaiban. Semuanya ada di Jawa. Ia hanya bekerja “dengan sendirinya”. Untuk kenyamanan kita. <h2>Raih</h2>
Autoboxing dan unboxing di Java - 5
Alat apa pun, jika digunakan secara tidak benar, akan menjadi senjata yang tangguh untuk melawan dirinya sendiri. Dan mekanisme tinju/unboxing otomatis di Java tidak terkecuali. Perbandingan pertama yang jelas adalah melalui ==. Saya pikir ini sudah jelas, tapi mari kita lihat lagi:
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 kasus pertama, nilai diambil dari Integercache nilai (lihat penjelasan Boxing di atas), dan dalam kasus kedua, objek baru akan dibuat setiap saat. Tapi di sini ada baiknya melakukan reservasi. Perilaku ini bergantung pada batas tinggi cache ( java.lang.Integer.IntegerCache.high ). Selain itu, batas ini dapat berubah karena pengaturan lainnya. Anda dapat membaca pembahasan topik ini di stackoverflow: Seberapa besar cache Integer? Secara alami, objek perlu dibandingkan menggunakan persamaan: System.out.println(notInCache.equals(notInCache2)); Masalah kedua yang terkait dengan mekanisme yang sama adalah kinerja. Tinju apa pun di Java sama dengan membuat objek baru. Jika nomor tersebut tidak termasuk dalam nilai cache (yaitu -128 hingga 127), maka objek baru akan dibuat setiap saat. Jika tiba-tiba pengemasan (yaitu pengepakan) dilakukan secara berulang-ulang, hal ini akan menyebabkan peningkatan besar pada benda-benda yang tidak diperlukan dan konsumsi sumber daya untuk pekerjaan pemulung. Oleh karena itu, jangan terlalu gegabah dalam melakukannya. Penggaruk ketiga yang tidak kalah menyakitkan berasal dari mekanisme yang sama:
public static void check(Integer value) {
    if (value <= 0) {
        throw new IllegalStateException("Value is too small");
    }
}
Dalam kode ini, orang tersebut jelas-jelas berusaha untuk tidak melewati kesalahannya. Tapi tidak ada pemeriksaan untuk itu null. Jika menyangkut masukan null, maka alih-alih kesalahan yang dapat dimengerti, kita akan mendapatkan kesalahan yang tidak dapat dipahami NullPointerException. Karena sebagai perbandingan, Java akan mencoba mengeksekusi value.intValuedan crash, karena... valueakan null. <h2>Kesimpulan</h2>Mekanisme boxing/unboxing memungkinkan programmer untuk menulis lebih sedikit kode dan terkadang bahkan tidak berpikir untuk mengkonversi dari primitif ke objek dan sebaliknya. Namun bukan berarti Anda harus melupakan cara kerjanya. Jika tidak, Anda mungkin membuat kesalahan yang mungkin tidak langsung muncul. Kita tidak boleh bergantung pada bagian sistem yang tidak sepenuhnya berada di bawah kendali kita (seperti batas bilangan bulat). Namun jangan lupakan semua kelebihan kelas wrapper (seperti Integer). Seringkali kelas wrapper ini memiliki serangkaian metode statis tambahan yang akan membuat hidup Anda lebih baik dan kode Anda lebih ekspresif. Berikut ini contoh mengejar ketinggalan:
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 benar dari semuanya adalah tidak ada keajaiban, yang ada semacam realisasi. Dan tidak semuanya akan selalu seperti yang kita harapkan. Misalnya tidak ada pengemasan: System.out.println("The number is " + 8); Contoh di atas akan dioptimasi oleh compiler menjadi satu baris. Artinya, seolah-olah Anda menulis “Angkanya 8”. Dan pada contoh di bawah ini juga tidak akan ada kemasannya:
public static void main(String[] args) {
    System.out.println("The number is " + Math.abs(-2));
}
Bagaimana jadinya ketika kita printlnmengambil suatu objek sebagai masukan dan perlu menghubungkan garis-garisnya. Garis... iya makanya tidak ada kemasan seperti itu. Ada Integermetode statis, tetapi beberapa di antaranya adalah package. Artinya, kita tidak bisa menggunakannya, tapi di Java sendiri bisa digunakan secara aktif. Inilah yang terjadi di sini. Metode getChars akan dipanggil, yang membuat array karakter dari nomor tersebut. Sekali lagi, tidak ada keajaiban, hanya Java). Jadi, dalam situasi apa pun yang tidak jelas, Anda hanya perlu melihat implementasinya dan setidaknya sesuatu akan terjadi. #Viacheslav
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION