Saya mencari jawaban yang jelas, singkat dan akurat.
Idealnya sebagai jawaban aktual, meskipun tautan ke penjelasan yang baik disambut.
Saya mencari jawaban yang jelas, singkat dan akurat.
Idealnya sebagai jawaban aktual, meskipun tautan ke penjelasan yang baik disambut.
language-but-not-type-agnostic
?static-language-agnostic
? Saya tidak yakin bahwa SO membutuhkan perbedaan; mungkin pertanyaan yang bagus untuk meta.Jawaban:
Nilai kotak adalah struktur data yang pembungkus minimal di sekitar tipe primitif *. Nilai kotak biasanya disimpan sebagai pointer ke objek di heap .
Dengan demikian, nilai-nilai kotak menggunakan lebih banyak memori dan mengambil minimal dua pencarian memori untuk mengakses: satu untuk mendapatkan pointer, dan satu lagi untuk mengikuti pointer itu ke primitif. Jelas ini bukan hal yang Anda inginkan dalam lingkaran batin Anda. Di sisi lain, nilai kotak biasanya bermain lebih baik dengan tipe lain dalam sistem. Karena mereka adalah struktur data kelas satu dalam bahasa, mereka memiliki metadata yang diharapkan dan struktur yang dimiliki oleh struktur data lainnya.
Di Java dan Haskell, koleksi umum tidak dapat berisi nilai yang tidak dikotak. Koleksi umum di .NET dapat menyimpan nilai yang tidak dikotak tanpa hukuman. Di mana generik Java hanya digunakan untuk pengecekan tipe waktu-kompilasi, .NET akan menghasilkan kelas-kelas khusus untuk setiap tipe generik yang dipakai saat run time .
Java dan Haskell memiliki larik tanpa kotak, tetapi mereka jelas kurang nyaman daripada koleksi lainnya. Namun, ketika kinerja puncak diperlukan, ada baiknya sedikit ketidaknyamanan untuk menghindari overhead tinju dan unboxing.
* Untuk diskusi ini, nilai primitif adalah apa pun yang dapat disimpan di tumpukan panggilan , alih-alih disimpan sebagai penunjuk ke nilai di heap. Seringkali itu hanya tipe mesin (int, float, dll), struct, dan terkadang array berukuran statis. .NET-land menyebutnya tipe nilai (berbeda dengan tipe referensi). Orang Jawa menyebutnya tipe primitif. Haskellions hanya memanggilnya tanpa kotak.
** Saya juga fokus pada Java, Haskell, dan C # dalam jawaban ini, karena itulah yang saya tahu. Untuk apa nilainya, Python, Ruby, dan Javascript semua memiliki nilai kotak khusus. Ini juga dikenal sebagai pendekatan "Semuanya adalah objek".
*** Peringatan: Kompiler / JIT yang cukup canggih dalam beberapa kasus dapat benar-benar mendeteksi bahwa nilai yang kotak semantik ketika melihat sumbernya, dapat dengan aman menjadi nilai yang tidak kotak pada saat runtime. Intinya, terima kasih kepada pelaksana bahasa yang brilian, kotak Anda terkadang gratis.
sumber
dari C # 3.0 Singkatnya :
sumber
Boxing & unboxing adalah proses mengubah nilai primitif menjadi kelas pembungkus berorientasi objek (tinju), atau mengubah nilai dari kelas pembungkus berorientasi objek kembali ke nilai primitif (unboxing).
Sebagai contoh, di java, Anda mungkin perlu mengubah
int
nilai menjadiInteger
(tinju) jika Anda ingin menyimpannya diCollection
karena primitif tidak dapat disimpan dalam objekCollection
, hanya. Tetapi ketika Anda ingin mendapatkannya kembali dariCollection
Anda mungkin ingin mendapatkan nilai sebagaiint
dan bukanInteger
jadi Anda akan membuka kotaknya.Boxing dan unboxing pada dasarnya tidak buruk , tetapi merupakan tradeoff. Tergantung pada implementasi bahasa, itu bisa lebih lambat dan lebih banyak memori intensif daripada hanya menggunakan primitif. Namun, ini juga memungkinkan Anda untuk menggunakan struktur data tingkat yang lebih tinggi dan mencapai fleksibilitas yang lebih besar dalam kode Anda.
Saat ini, ini paling sering dibahas dalam konteks fitur Java (dan bahasa lainnya) "autoboxing / autounboxing". Berikut ini adalah penjelasan java centric tentang autoboxing .
sumber
Di .Net:
Seringkali Anda tidak dapat bergantung pada jenis variabel yang akan dikonsumsi suatu fungsi, jadi Anda perlu menggunakan variabel objek yang memanjang dari penyebut umum terendah - di .Net ini
object
.Namun
object
adalah kelas dan menyimpan isinya sebagai referensi.Meskipun keduanya memiliki informasi yang sama, daftar kedua lebih besar dan lebih lambat. Setiap nilai dalam daftar kedua sebenarnya adalah referensi ke
object
yang memilikiint
.Ini disebut kotak karena
int
dibungkus olehobject
. Ketika dilemparkan kembali,int
kotaknya tidak - dikonversi kembali ke nilainya.Untuk tipe nilai (yaitu semua
structs
) ini lambat, dan berpotensi menggunakan lebih banyak ruang.Untuk tipe referensi (yaitu semua
classes
), ini jauh dari masalah, karena mereka tetap disimpan sebagai referensi.Masalah lebih lanjut dengan tipe nilai kotak adalah bahwa tidak jelas bahwa Anda berurusan dengan kotak, bukan nilai. Ketika Anda membandingkan dua
structs
maka Anda membandingkan nilai, tetapi ketika Anda membandingkan duaclasses
lalu (secara default) Anda membandingkan referensi - yaitu apakah ini contoh yang sama?Ini bisa membingungkan ketika berhadapan dengan tipe nilai kotak:
Sangat mudah untuk dikerjakan:
Namun itu adalah hal lain yang harus diperhatikan ketika berhadapan dengan nilai-nilai kotak.
sumber
Object
tidak mengimplementasikan operator kesetaraan, tetapi tipe kelas dapat dibandingkan denganIs
operator; sebaliknya,Int32
dapat digunakan dengan operator kesetaraan, tetapi tidakIs
. Perbedaan itu membuatnya jauh lebih jelas jenis perbandingan apa yang sedang dilakukan.Boxing
adalah proses konversi tipe nilai menjadi tipe referensi. SedangkanUnboxing
konversi dari tipe referensi menjadi tipe nilai.Jenis nilai adalah:
int
,char
danstructures
,enumerations
. Jenis referensi adalah:Classes
,interfaces
,arrays
,strings
danobjects
sumber
Koleksi generik .NET FCL:
semuanya dirancang untuk mengatasi masalah kinerja tinju dan unboxing dalam implementasi pengumpulan sebelumnya.
Untuk lebih lanjut, lihat bab 16, CLR via C # (Edisi ke-2) .
sumber
Boxing dan unboxing memfasilitasi tipe nilai untuk diperlakukan sebagai objek. Tinju berarti mengonversi nilai menjadi turunan dari jenis referensi objek. Sebagai contoh,
Int
adalah kelas danint
tipe data. Konversiint
keInt
adalah contoh tinju, sedangkan konversiInt
keint
adalah unboxing. Konsep ini membantu dalam pengumpulan sampah, di Unboxing, di sisi lain, mengubah tipe objek menjadi tipe nilai.sumber
var ii = 123; typeof ii
kembalinumber
.var iiObj = new Number(123); typeof iiObj
kembaliobject
.typeof ii + iiObj
kembalinumber
. Jadi ini setara dengan javascript tinju. Nilai iiObj secara otomatis dikonversi ke nomor primitif (tanpa kotak) untuk melakukan aritmatika dan mengembalikan nilai tanpa kotak.Seperti yang lainnya, autoboxing bisa bermasalah jika tidak digunakan dengan hati-hati. Klasik adalah berakhir dengan NullPointerException dan tidak dapat melacaknya. Bahkan dengan debugger. Coba ini:
sumber
i
diinisialisasi sebelum waktunya. Entah menjadikannya deklarasi kosong (Integer i;
) sehingga kompiler dapat menunjukkan bahwa Anda lupa untuk menginisialisasi, atau menunggu untuk mendeklarasikannya sampai Anda tahu nilainya.