Kata pengantar
Artikel ini terutama memperkenalkan konten yang relevan tentang Integer di Java, dan membagikannya untuk referensi dan pembelajaran Anda. Saya tidak akan mengatakan banyak hal di bawah ini, mari kita lihat perkenalan terperinci bersama.
Parasit sungguhan
Beberapa hari yang lalu, saya melihat sebuah artikel yang dibagikan pada saat -saat saya "Mekanisme transmisi parameter fungsi Java - apakah Anda benar -benar memahaminya?》
Beberapa pemicu telah dipelajari di integer Java sebelumnya, jadi saya menulis artikel ini, berharap ini akan membantu Anda.
menukarkan
Pertama -tama mari kita lihat contohnya.
Harap gunakan Java untuk menyelesaikan fungsi swap dan menukar nilai dua jenis integer.
public static void test () melempar Exception {Integer A = 1, B = 2; swap (a, b); System.out.println ("a =" + a + ", b =" + b);} static void swap (integer a, integer b) {// bagian yang perlu diimplementasikan} Pertama
Jika Anda tidak mengerti bagaimana objek Java dialokasikan dalam memori dan bagaimana metode lulus parameter, Anda dapat menulis kode berikut.
public static void swapone (integer A, integer b) melempar pengecualian {integer atempvalue = a; a = b; b = atempValue;} Hasil menjalankan menunjukkan bahwa nilai -nilai A dan B tidak dipertukarkan.
Jadi mari kita lihat bagaimana objek Java dialokasikan dalam memori ketika program di atas berjalan:
Penugasan Alamat Objek
Dari sini kita dapat melihat bahwa tabel variabel lokal dari kedua metode tersebut memiliki referensi ke alamat data aktual objek A dan B.
Fungsi swap yang diimplementasikan di atas hanya pertukaran referensi ke variabel lokal A dan variabel lokal B dalam fungsi swap, dan tidak menukar data aktual dalam tumpukan JVM.
Oleh karena itu, data yang dirujuk oleh A dan B dalam fungsi utama tidak dipertukarkan, sehingga A dan B dari variabel lokal dalam fungsi utama tidak akan berubah.
Jadi, bagaimana Anda beroperasi saat menukar data di fungsi utama?
Kedua kalinya
Menurut praktik di atas, dapatkah kita mempertimbangkan pertukaran nilai data A dan B pada tumpukan JVM?
Mari kita pelajari secara singkat tentang objek Integer. Ini hanya memiliki nilai tipe int tingkat objek untuk mewakili nilai objek.
Jadi kami menggunakan refleksi untuk memodifikasi nilainya, kodenya adalah sebagai berikut:
public static void swaptwo (Integer A1, Integer B1) melempar Exception {field valuefield = integer.class.getDeclaredfield ("value"); valuefield.setAccessible (true); int tempavalue = valuefield.getint (a1); valuefield.setint (a1, b1.intvalue ()); valuefield.setint (b1, tempavalue);}Hasil operasi sejalan dengan harapan.
kejutan
Setelah program di atas dijalankan, apa yang akan terjadi jika saya menyatakan Integer c = 1, d = 2;
Program sampel adalah sebagai berikut:
public static void swaptwo (Integer A1, Integer B1) melempar Exception {field valuefield = integer.class.getDeclaredfield ("value"); valuefield.setAccessible (true); int tempavalue = valuefield.getint (a1); valuefield.setint (a1, b1.intvalue ()); valuefield.setint (b1, tempaValue);} public static void testThree () melempar Exception {integer a = 1, b = 2; swaptwo (a, b); System.out.println ("a =" + a + "; b =" + b); Integer C = 1, D = 2; System.out.println ("c =" + c + "; d =" + d);}Hasil output adalah sebagai berikut:
a = 2; b = 1c = 2; D = 1
Kejutan atau tidak! Kecelakaan atau tidak! Merangsang atau tidak!
Secara mendalam
Apa sebenarnya yang terjadi? Mari kita lihat kode yang didekompilasi:
Penulis menggunakan alat IDE untuk secara langsung mendekompilasi file .class ini
public static void testThree () melempar Exception {integer a = integer.valueof (1); Integer b = integer.valueof (2); swaptwo (a, b); System.out.println ("a =" + a + "; b =" + b); Integer c = integer.valueof (1); Integer d = integer.valueof (2); System.out.println ("c =" + c + "; d =" + d);} Dalam proses java secara otomatis tinju, tipe asli int ke tipe integer Integer.valueOf(int) digunakan.
Pasti bahwa metode ini merangkum beberapa operasi secara internal, yang menyebabkan kita memiliki dampak global setelah memodifikasi Integer.value . Nilai.
Semua ini melibatkan kode di bagian kode ini direkatkan sekaligus (PS: penulis yang tidak menyeret adalah pembuat kode yang baik):
Kelas Publik Integer { / ** * @since 1.5 * / Nilai integer statis publik (int i) {if (i> = integercache.low && i <= integercache.high) return integercache.cache [i + (-intercercache.low)]]; mengembalikan bilangan bulat baru (i); } private static class integercache {static final int low = -128; statis final int high; cache integer final statis []; static {// nilai tinggi dapat dikonfigurasi oleh properti int h = 127; String integercacheHighPropValue = sun.misc.vm.getsavedproperty ("java.lang.integer.integercache.high"); if (integercacheHighpropValue! = null) {coba {int i = parseInt (integercacheHighPropValue); i = Math.max (i, 127); // Ukuran array maksimum adalah integer.max_value h = math.min (i, integer.max_value -(-low) -1); } catch (NumberFormateException NFE) {// Jika properti tidak dapat diuraikan ke int, abaikan. }} tinggi = h; cache = bilangan bulat baru [(tinggi - rendah) + 1]; int j = rendah; untuk (int k = 0; k <cache.length; k ++) cache [k] = bilangan bulat baru (j ++); // rentang [-128, 127] harus diinternir (JLS7 5.1.7) menegaskan integercache.high> = 127; } private integercache () {}} Seperti yang ditunjukkan di atas, Integer memiliki integercache kelas statis pribadi di dalamnya, yang secara statis menginisialisasi array integer yang berisi Integer.IntegerCache.low ke java.lang.Integer.IntegerCache.high .
Kisaran nilai java.lang.Integer.IntegerCache.high adalah antara [127~Integer.MAX_VALUE - (-low) -1] .
Semua objek yang dikembalikan oleh fungsi Integer.valueOf(int) dalam interval ini adalah offset yang dihitung berdasarkan nilai int dan diperoleh dari array Integer.IntegerCache.cache . Objeknya sama dan tidak ada objek baru yang dibuat.
Jadi ketika kami memodifikasi nilai Integer.valueOf(1) , semua nilai pengembalian Integer.IntegerCache.cache[ 1 - IntegerCache.low ] akan diubah.
Saya yakin IQ Anda harus dipahami. Jika Anda tidak mengerti, silakan hubungi 10086 di bagian komentar.
Oke, jadi bagaimana dengan bagian yang tidak ada di [IntegerCache.low~IntegerCache.high) ?
Jelas, mereka beruntung, tidak di -cache oleh integercache, dan setiap kali mereka tiba, mereka akan mengalokasikan sepotong bumi (pedalaman) (distribusi) di JVM.
Lamunan
Bagaimana jika saya mengubah parameter yang dikonversi untuk mengetik ke int?
public static void testone () melempar Exception {int a = 1, b = 2; swapone (a, b); System.out.println ("a =" + a + ", b =" + b);} static void swapone (int a, int b) {// bagian yang perlu diimplementasikan} Dengan keterampilan penulis saat ini, tidak ada solusi. Para ahli dapat meninggalkan pesan di akun resmi, terima kasih banyak!
Sejauh ini, bagian swap telah selesai.
1 + 1
Pertama mari kita lihat kodenya:
public static void testone () {int satu = 1; int dua = satu + satu; System.out.printf ("dua =%d", dua);} Apa outputnya?
Jika Anda mengatakan 2 untuk memastikan, maka Anda telah mempelajarinya dengan sia -sia, silakan hubungi 95169 secara langsung.
Saya dapat memberi tahu Anda dengan pasti bahwa itu bisa menjadi nilai apa pun dalam interval [Integer.MIN_VALUE~Integer.MAX_VALUE] .
Kejutan atau tidak! Kecelakaan atau tidak! Merangsang atau tidak!
Mari kita membelai kode panggang satu per satu.
Penulis menggunakan alat IDE untuk secara langsung mendekompilasi file .class ini
public static void testone () {int satu = 1; int dua = satu + satu; System.out.printf ("dua =%d", dua);} Variabel dua di sini tidak memanggil teger.valueOf(int) , yang berbeda dari apa yang saya bayangkan. Saya menduga ini adalah pot IDE.
Jadi periksa bytecode yang dikompilasi dengan tegas. Berikut ini adalah beberapa bytecode dari kutipan:
Ldc "dua =%d" iconst_1anewarray java/lang/objectdupiconsst_0iload 2invokestatic java/lang/integer.valueof (i) ljava/lang/integer; aastoreinvokevirtual java/io/printstream.pristf (Ljava/lang/string; [ljava/lang/objek;) ljava/io/printstream; pop
Dapat dilihat bahwa itu memang pot IDE. Tidak hanya Integer.valueOf(int) disebut sekali, tetapi array objek juga dibuat.
Kode Java lengkap akan terlihat seperti ini:
public static void testone () {int satu = 1; int dua = satu + satu; Objek [] params = {integer.valueof (dua)}; System.out.printf ("dua =%d", params);} Jadi cukup modifikasi nilai Integer.IntegerCache.cache[2+128] sebelum metode dipanggil, jadi tambahkan beberapa kode ke bagian inisialisasi statis kelas.
kelas publik oneplusone {static {try {class <?> cacheclazz = class.forname ("java.lang.integer $ integercache"); Field Cachefield = cacheclazz.getDeclaredfield ("cache"); cachefield.setAccessible (true); Integer [] cache = (integer []) cacheField.get (null); // Ubah di sini menjadi 1 + 1 = 3 cache [2 + 128] = bilangan bulat baru (3); } catch (Exception e) {E.PrintStackTrace (); }} public static void testone () {int One = 1; int dua = satu + satu; System.out.printf ("dua =%d", dua); }}dua == 2?
Setelah memodifikasi nilai Integer.IntegerCache.cache[2 + 128] , apakah variabel dua sama dengan 2?
public static void testTwo () {int satu = 1; int dua = satu + satu; System.out.println (dua == 2); System.out.println (integer.valueof (dua) == 2);}Output kode di atas adalah sebagai berikut
Truefalse
Karena dua == 2 tidak melibatkan konversi tinju integer, atau perbandingan dari jenis aslinya, 2 dari tipe asli selalu sama dengan 2.
Bentuk sebenarnya dari Integer.valueOf(two)==2 adalah Integer.valueOf(two).intValue == 2 , yaitu, 3 == 2, jadi salah.
Di sini kita dapat melihat bahwa jika Anda membandingkan nilai null dengan variabel integer dengan variabel int dengan tanda ganda yang sama, nullPointException akan dilemparkan.
Jenis output apa jika metode di sini digantikan oleh System.out.println("Two=" + two) ? Anda bisa mencobanya.
nota bene
Xcache
| baik | Apakah ada cache | Nilai minimum | Nilai maksimum |
|---|---|---|---|
| Boolean | tidak ada | - | - |
| Byte | Bytecache | -128 | 127 (diperbaiki) |
| Pendek | SPRINTCACHE | -128 | 127 (diperbaiki) |
| Karakter | Charactercache | 0 | 127 (diperbaiki) |
| Bilangan bulat | Integercache | -128 | java.lang.integer.integercache.high |
| Panjang | Longcache | -128 | 127 (diperbaiki) |
| Mengambang | tidak ada | - | - |
| Dobel | tidak ada | - | - |
java.lang.integer.integercache.high
Setelah membaca metode mendapatkan tinggi sun.misc.VM.getSavedProperty kelas integercache, Anda mungkin memiliki pertanyaan berikut. Kami tidak akan menunda dan menggunakan metode satu pertanyaan-satu-jawaban.
1. Bagaimana cara meneruskan nilai ini ke JVM?
Seperti properti sistem, ketika JVM dimulai, dilewati dengan pengaturan -Djava.lang.Integer.IntegerCache.high=xxx .
2. Apa perbedaan antara metode ini dan System.getProperty ?
Untuk membedakan parameter yang diperlukan oleh sistem JVM dari parameter yang digunakan oleh pengguna,
Ketika java.lang.System.initializeSystemClass dimulai, parameter startup akan disimpan di dua tempat:
2.1 Parameter sistem yang diterima oleh semua JVM disimpan di sun.misc.vm.savedprops.
Ketika JVM dimulai, ia memanggil metode java.lang.System.initializeSystemClass untuk menginisialisasi properti.
Pada saat yang sama, metode sun.misc.VM.saveAndRemoveProperties juga akan dipanggil untuk menghapus properti berikut dari java.lang.System.props :
Properti yang tercantum di atas adalah semua parameter sistem yang perlu ditetapkan untuk startup JVM, jadi untuk pertimbangan keamanan dan pertimbangan isolasi, pisahkan dari sistem yang dapat diakses pengguna.
2.2 Simpan parameter lain kecuali parameter berikut yang diperlukan untuk startup JVM di java.lang.system.props.
PS: JDK 1.8.0_91 digunakan oleh penulis
Integercache untuk Java 9
Bayangkan jika gameplay nakal di atas muncul dalam paket ketergantungan pihak ketiga, pasti akan ada sekelompok programmer yang akan menjadi gila (tolong jangan mencoba gameplay yang buruk, konsekuensinya sangat serius).
Untungnya, Java 9 telah membatasi ini. Anda dapat menulis file modul-info.java dalam modul yang sesuai, yang membatasi penggunaan refleksi untuk mengakses anggota, dll. Setelah deklarasi sesuai kebutuhan, kode hanya dapat mengakses bidang, metode, dan informasi lain yang dapat diakses dengan refleksi. Hanya ketika kelas dalam modul yang sama, atau modul telah membuka paket untuk akses refleksi. Untuk detailnya, silakan merujuk ke artikel:
Ubah Integercache di Java 9?
Terima kasih kepada Lydia dan Asuka atas saran mereka yang berharga dan kerja keras untuk proofreading.
Akhirnya, saya ingin berbagi dengan Anda masalah yang tidak saya perhatikan pada nilai integer di Java:
Pertama -tama mari kita lihat cuplikan kode:
public static void main (string [] args) {integer a1 = integer.valueof (60); // Danielinbiti Integer B1 = 60; System.out.println ("1: ="+(a1 == B1)); Integer A2 = 60; Integer B2 = 60; System.out.println ("2: ="+(a2 == b2)); Integer a3 = bilangan bulat baru (60); Integer B3 = 60; System.out.println ("3: ="+(a3 == B3)); Integer a3 = bilangan bulat baru (60); Integer B3 = 60; System.out.println ("3: ="+(a3 == B3)); Integer A4 = 129; Integer B4 = 129; System.out.println ("4: ="+(a4 == b4)); } Jika hasil perbandingan kode ini tidak dijalankan, saya tidak tahu apa jawabannya dalam pikiran Anda.
Untuk mengetahui jawaban ini, ini melibatkan java buffer dan masalah tumpukan.
Di Java, tipe integer adalah buffer untuk angka antara -128-127, sehingga konsisten dengan tanda yang sama. Tetapi untuk angka yang tidak dalam kisaran ini, mereka baru di tumpukan. Oleh karena itu, ruang alamat berbeda, sehingga tidak sama.
Integer b3=60 , ini adalah proses pengemasan, yaitu, Integer b3=Integer.valueOf(60)
Oleh karena itu, di masa depan, ketika Anda bertemu Integer, Anda perlu menggunakan intValue() untuk membandingkan apakah nilainya sama.
Tidak ada buffer untuk ganda.
Menjawab
1: = Benar
2: = Benar
3: = Salah
4: = false
Meringkaskan
Di atas adalah seluruh konten artikel ini. Saya berharap konten artikel ini memiliki nilai referensi tertentu untuk studi atau pekerjaan semua orang. Jika Anda memiliki pertanyaan, Anda dapat meninggalkan pesan untuk berkomunikasi. Terima kasih atas dukungan Anda ke wulin.com.