Saya tahu ini mungkin sangat bodoh, tetapi banyak tempat mengklaim bahwa kelas Integer di Java tidak dapat diubah, namun kode berikut:
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Melaksanakan tanpa kesulitan memberikan hasil (yang diharapkan) 6. Jadi secara efektif nilai a telah berubah. Bukankah itu berarti Integer bisa berubah? Pertanyaan sekunder dan sedikit offtopic: "Kelas yang tidak berubah tidak membutuhkan konstruktor salinan". Ada yang mau menjelaskan kenapa?
java
immutability
mutable
K.Steff
sumber
sumber
Jawaban:
Kekekalan tidak berarti bahwa
a
tidak pernah bisa menyamai nilai lain. Misalnya,String
tidak dapat diubah juga, tetapi saya masih bisa melakukan ini:str
tidak diubah, melainkanstr
sekarang menjadi objek yang sama sekali baru dibuat, sama seperti milik AndaInteger
. Jadi nilaia
tidak bermutasi, tetapi diganti dengan objek yang sama sekali baru, yaitunew Integer(6)
.sumber
+=
operasi.Integer.valueOf(int)
dan metode itu memelihara cacheInteger
objek. Jadi hasil dari+=
sebuahInteger
variabel bisa jadi objek yang sebelumnya ada (atau bahkan bisa jadi objek yang sama ... dalam kasusa += 0
).a
adalah "referensi" ke beberapa Integer (3), singkatan Andaa+=b
benar-benar berarti melakukan ini:Jadi tidak, bilangan bulat tidak bisa diubah, tetapi variabel yang mengarah padanya adalah *.
* Ada kemungkinan untuk memiliki variabel yang tidak dapat diubah, ini dilambangkan dengan kata kunci
final
, yang berarti bahwa referensi tidak dapat berubah.sumber
Anda dapat menentukan bahwa objek telah berubah menggunakan
System.identityHashCode()
(Cara yang lebih baik adalah menggunakan biasa==
namun tidak begitu jelas bahwa referensi daripada nilainya telah berubah)cetakan
Anda dapat melihat "id" yang mendasari objek yang
a
dirujuk telah berubah.sumber
Untuk pertanyaan awal yang diajukan,
Integer tidak dapat diubah, jadi yang terjadi di atas adalah 'a' telah berubah menjadi referensi baru dengan nilai 6. Nilai awal 3 dibiarkan tanpa referensi di memori (belum diubah), sehingga dapat dikumpulkan sampahnya.
Jika ini terjadi pada String, String akan disimpan di pool (dalam ruang PermGen) untuk jangka waktu yang lebih lama daripada Integer karena diharapkan memiliki referensi.
sumber
Ya, Integer tidak dapat diubah.
A adalah referensi yang menunjuk ke suatu objek. Ketika Anda menjalankan + = 3, itu menetapkan kembali A untuk mereferensikan objek Integer baru, dengan nilai yang berbeda.
Anda tidak pernah memodifikasi objek aslinya, melainkan Anda mengarahkan referensi ke objek lain.
Baca tentang perbedaan antara objek dan referensi di sini .
sumber
Tidak dapat diubah tidak berarti bahwa Anda tidak dapat mengubah nilai variabel. Ini hanya berarti bahwa setiap tugas baru membuat objek baru (menugaskannya ke lokasi memori baru) dan kemudian nilainya ditetapkan ke sana.
Untuk memahami ini sendiri, lakukan tugas Integer dalam satu loop (dengan integer dideklarasikan di luar loop) dan lihat objek langsung dalam memori.
Alasan mengapa konstruktor salinan tidak diperlukan untuk objek yang tidak dapat diubah adalah akal sehat yang sederhana. Karena setiap tugas membuat objek baru, bahasa secara teknis sudah membuat salinan, jadi Anda tidak perlu membuat salinan lain.
sumber
Alasannya adalah bahwa jarang ada kebutuhan untuk menyalin (atau bahkan tujuan apa pun dalam menyalin) sebuah instance dari kelas yang tidak dapat diubah. Salinan objek harus "sama dengan" aslinya, dan jika sama, tidak perlu membuatnya.
Ada beberapa asumsi yang mendasari:
Ini mengasumsikan bahwa aplikasi Anda tidak memberi arti apa pun pada identitas objek instance kelas.
Ini mengasumsikan bahwa kelas telah kelebihan beban
equals
danhashCode
salinan instance akan menjadi "sama dengan" aslinya ... menurut metode ini.Salah satu atau kedua asumsi tersebut bisa salah, dan itu mungkin memerlukan penambahan konstruktor salinan.
sumber
Inilah cara saya memahami kekekalan
Jika int bisa bermutasi, "a" akan mencetak 8 tetapi tidak karena itu tidak berubah, itulah mengapa itu 3. Contoh Anda hanyalah sebuah tugas baru.
sumber
Saya dapat menjelaskan bahwa Integer (dan kredo lainnya seperti Float, Short dll) tidak dapat diubah dengan kode contoh sederhana:
Hasilnya datang ke he Hi There 100 bukannya hasil yang diharapkan (dalam kasus sb dan saya menjadi objek yang bisa berubah) Hi There 1000
Ini menunjukkan bahwa objek yang dibuat oleh i di main tidak dimodifikasi, sedangkan sb dimodifikasi.
Jadi StringBuilder mendemonstrasikan perilaku yang bisa berubah tetapi bukan Integer.
Jadi Integer Tidak Berubah. Oleh karena itu Terbukti
sumber
private void doStringBuilder(StringBuilder sb){ sb = new StringBuilder(); }
makasb
tidak berubah.private void doInteger(Integer i){ System.out.println( i == 100 ); i=1000; System.out.println( i == 100 ); }
Outputnya adalah:
Hai Bye 1000 5000 1000 5000 d a
Jadi char bisa berubah, String Integer dan int tidak bisa diubah.
sumber