<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.
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:
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:
Artinya, pada intinya, yang baru akan diambil
Seperti yang Anda lihat, tidak ada keajaiban. Semuanya ada di Jawa. Ia hanya bekerja “dengan sendirinya”. Untuk kenyamanan kita. <h2>Raih</h2>
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
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 String
parameter, kita mendapatkannya Integer
dengan 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.class
di mana App.class adalah file kelas yang dikompilasi untuk kelas Anda. Kita akan melihat konten seperti ini:
Integer
atau akan diperoleh Integer
dari cache (cache tidak lebih dari sekedar array Integer) tergantung pada nilai angkanya. Tentu saja, Integer
tidak 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.asList
tidak akan membuat dari int[]
untuk kita List
dari 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.abs
hanya menerima primitif. Apa yang harus dilakukan? Kelas wrapper memiliki metode khusus untuk kasus ini yang mengembalikan primitif. Misalnya, ini adalah Integer
metode intValue . Kalau kita lihat bytecode-nya seperti ini:
==
. 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 Integer
cache 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.intValue
dan crash, karena... value
akan 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 println
mengambil suatu objek sebagai masukan dan perlu menghubungkan garis-garisnya. Garis... iya makanya tidak ada kemasan seperti itu. Ada Integer
metode 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
GO TO FULL VERSION