Perhatikan contoh berikut.
String str = new String();
str = "Hello";
System.out.println(str); //Prints Hello
str = "Help!";
System.out.println(str); //Prints Help!
Sekarang, di Jawa, objek String tidak dapat diubah. Lalu bagaimana bisa benda itustr
tersebut diberi nilai "Bantuan!". Bukankah ini bertentangan dengan kekekalan string di Jawa? Adakah yang bisa menjelaskan konsep imutabilitas yang tepat?
Edit:
Baik. Saya sekarang mengerti, tetapi hanya satu pertanyaan lanjutan. Bagaimana dengan kode berikut:
String str = "Mississippi";
System.out.println(str); // prints Mississippi
str = str.replace("i", "!");
System.out.println(str); // prints M!ss!ss!pp!
Apakah ini berarti bahwa dua objek dibuat lagi ("Mississippi" dan "M! Ss! Ss! Pp!") Dan referensi str
menunjuk ke objek yang berbeda setelah replace()
metode?
java
string
immutability
Light_handle
sumber
sumber
Jawaban:
str
bukan objek, ini referensi ke objek."Hello"
dan"Help!"
duaString
benda berbeda . Dengan demikian,str
menunjuk ke sebuah string. Anda dapat mengubah apa yang ditunjukkannya , tetapi bukan apa yang ditunjukkannya .Ambil kode ini, misalnya:
Sekarang, tidak ada 1 yang bisa kami lakukan untuk
s1
yang akan mempengaruhi nilais2
. Mereka merujuk ke objek yang sama - string"Hello"
- tetapi objek itu tidak berubah dan dengan demikian tidak dapat diubah.Jika kita melakukan sesuatu seperti ini:
Di sini kita melihat perbedaan antara bermutasi suatu objek, dan mengubah referensi.
s2
masih menunjuk ke objek yang sama seperti yang kita setel awalnyas1
. Pengaturans1
untuk"Help!"
hanya mengubah referensi , sedangkanString
objek yang awalnya dirujuk tetap tidak berubah.Jika string dapat diubah, kita dapat melakukan sesuatu seperti ini:
Edit untuk menanggapi edit OP:
Jika Anda melihat kode sumber untuk String.replace (char, char) (juga tersedia di src.zip di direktori instalasi JDK Anda - tip pro adalah untuk melihat ke sana setiap kali Anda bertanya-tanya bagaimana sesuatu benar-benar berfungsi) Anda dapat melihat apa yang dilakukannya adalah sebagai berikut:
oldChar
dalam string saat ini, buat salinan dari string saat ini di mana semua kemunculanoldChar
digantinewChar
.oldChar
tidak ada dalam string saat ini, kembalikan string saat ini.Jadi ya,
"Mississippi".replace('i', '!')
buatString
objek baru . Sekali lagi, yang berikut ini berlaku:Pekerjaan rumah Anda untuk saat ini adalah untuk melihat apa yang dilakukan kode di atas jika Anda berubah
s1 = s1.replace('i', '!');
menjadis1 = s1.replace('Q', '!');
:)1 Sebenarnya, itu adalah mungkin untuk string bermutasi (dan objek abadi lainnya). Ini membutuhkan refleksi dan sangat, sangat berbahaya dan tidak boleh digunakan kecuali Anda benar-benar tertarik menghancurkan program.
sumber
Objek yang
str
referensi dapat berubah, tetapiString
objek yang sebenarnya tidak bisa.The
String
benda yang mengandung string"Hello"
dan"Help!"
tidak dapat mengubah nilai-nilai mereka, maka mereka berubah.Kekekalan
String
objek tidak berarti bahwa referensi yang menunjuk ke objek tidak dapat berubah.Salah satu cara seseorang dapat mencegah perubahan
str
referensi adalah dengan mendeklarasikannya sebagaifinal
:Sekarang, mencoba untuk menetapkan lain
String
untukSTR
akan menyebabkan error kompilasi.sumber
str
bukan "objek" itu referensi ke objek. Jika Anda telahString str = "Hello";
diikuti olehString anotherReference = str;
Anda tidak memiliki 2 objek String, Anda memiliki satu objek (literal "Halo") dan 2 referensi untuk itu (str
dananotherReference
).Light_handle Saya sarankan Anda membaca Ukuran Cup - sebuah cerita tentang variabel dan Pass-by-Value Please (Ukuran Cup lanjutan) . Ini akan banyak membantu ketika membaca posting di atas.
Sudahkah Anda membacanya? Iya. Baik.
Ini menciptakan "remote control" baru yang disebut "
str
" dan menyetelnya ke nilainew String()
(atau""
).misalnya dalam memori ini menciptakan:
Ini kemudian mengubah "
str
" remote control tetapi tidak mengubah string asli""
.misalnya dalam memori ini menciptakan:
Ini kemudian mengubah "
str
" remote control tetapi tidak mengubah string asli""
atau objek yang saat ini menunjuk remote control.misalnya dalam memori ini menciptakan:
sumber
Mari kita istirahat menjadi beberapa bagian
Pernyataan ini menciptakan string yang berisi halo dan menempati ruang dalam memori yaitu di Constant String Pool dan dan menetapkannya ke objek referensi s1
Pernyataan ini memberikan string yang sama halo ke s2 referensi baru
Kedua referensi menunjuk ke string yang sama sehingga menghasilkan nilai yang sama seperti berikut.
Meskipun String tidak dapat diubah , penugasan dapat dimungkinkan sehingga s1 sekarang akan merujuk ke tumpukan nilai baru .
Tapi bagaimana dengan objek s2 yang menunjuk ke hello itu akan seperti apa adanya.
Karena String tidak dapat diubah Java Virtual Machine tidak akan mengizinkan kami untuk memodifikasi string s1 dengan metodenya. Ini akan membuat semua objek String baru di kumpulan sebagai berikut.
Catatan jika String akan bisa berubah maka output akan menjadi
Sekarang Anda mungkin terkejut mengapa String memiliki metode seperti concat () untuk dimodifikasi. Cuplikan berikut akan menghapus kebingungan Anda.
Di sini kita menetapkan nilai string yang dimodifikasi kembali ke referensi s1 .
Itu sebabnya Java memutuskan bahwa String adalah kelas final. Jika tidak, siapa pun dapat memodifikasi dan mengubah nilai string. Semoga ini bisa membantu sedikit.
sumber
Objek string yang pertama kali dirujuk oleh
str
tidak diubah, semua yang Anda lakukan adalah membuatstr
merujuk ke objek string baru.sumber
String tidak akan berubah, referensi untuk itu akan berubah. Anda membingungkan kekekalan dengan konsep
final
bidang. Jika suatu bidang dinyatakan sebagaifinal
, setelah ditetapkan, bidang itu tidak dapat dipindahkan.sumber
Mengenai penggantian bagian dari pertanyaan Anda, coba ini:
sumber
Meskipun java mencoba mengabaikannya,
str
tidak lebih dari sebuah pointer. Ini berarti bahwa ketika Anda pertama kali menulisstr = "Hello";
, Anda membuat objek yangstr
menunjuk. Ketika Anda menetapkan ulangstr
dengan menulisstr = "Help!";
, objek baru dibuat dan"Hello"
objek lama mendapat sampah yang dikumpulkan setiap kali java merasa seperti itu.sumber
Kekekalan menyiratkan bahwa nilai objek yang dipakai tidak dapat berubah, Anda tidak pernah dapat mengubah "Halo" menjadi "Bantuan!".
Str variabel adalah referensi ke objek, ketika Anda menetapkan nilai baru untuk str Anda tidak mengubah nilai objek yang dirujuk, Anda mereferensikan objek yang berbeda.
sumber
Kelas string tidak dapat diubah, dan Anda tidak dapat mengubah nilai objek tidak berubah. Tetapi dalam kasus String, jika Anda mengubah nilai string daripada itu akan membuat string baru dalam kumpulan string dan dari referensi string Anda ke nilai itu bukan yang lebih lama. jadi dengan cara ini string tidak dapat diubah. Mari kita ambil contoh,
itu akan membuat satu string "Mississippi" dan akan menambahkannya ke kolam String jadi sekarang str menunjuk ke Mississippi.
Tetapi setelah operasi di atas, satu string lain akan dibuat "M! Ss! Ss! Pp!" dan itu akan ditambahkan ke kolam String. dan sekarang str menunjuk ke M! ss! ss! pp !, bukan Mississippi.
jadi dengan cara ini ketika Anda akan mengubah nilai objek string itu akan membuat satu objek lagi dan akan menambahkannya ke kumpulan string.
Mari kita punya satu contoh lagi
tiga baris di atas ini akan menambahkan tiga objek string ke string pool.
1) Halo
2) Dunia
3) HelloWorld
sumber
Menggunakan:
Jika Anda lihat di sini saya menggunakan
concat
metode untuk mengubah string asli, yaitu, "String Baru" dengan string "String Ditambahkan", tapi masih saya mendapatkan output seperti sebelumnya, maka itu membuktikan bahwa Anda tidak dapat mengubah referensi objek kelas String, tetapi jika Anda melakukan hal ini dengan kelas StringBuilder itu akan berhasil. Itu tercantum di bawah ini.sumber
Seperti yang dikatakan Linus Tolvards:
Lihatlah ini:
Outputnya adalah
Jadi, ingat dua hal:
sumber
Bagi mereka yang bertanya-tanya bagaimana cara memecahkan String immutability di Java ...
Kode
Keluaran
sumber
String tidak berubah . Yang artinya kita hanya bisa mengubah referensi .
sumber
Di Jawa, objek umumnya diakses oleh referensi. Dalam potongan kode Anda str adalah referensi yang pertama kali ditugaskan untuk "Halo" (objek yang dibuat secara otomatis atau diambil dari kumpulan konstan ) dan kemudian Anda menetapkan objek lain "Bantuan!" untuk referensi yang sama. Poin yang perlu diperhatikan adalah referensi sama dan dimodifikasi, tetapi objek berbeda. Satu hal lagi dalam kode Anda, Anda mengakses tiga objek,
Memanggil String baru () membuat objek baru bahkan jika itu ada di string pool, jadi umumnya tidak boleh digunakan. Untuk meletakkan string yang dibuat dari String baru () ke dalam kumpulan string, Anda dapat mencoba
intern()
metode ini.Saya harap ini membantu.
sumber
Kekekalan yang bisa saya katakan adalah bahwa Anda tidak dapat mengubah String itu sendiri. Misalkan Anda memiliki String x, nilainya "abc". Sekarang Anda tidak dapat mengubah String, yaitu, Anda tidak dapat mengubah karakter apa pun di "abc".
Jika Anda harus mengubah karakter apa pun di String, Anda dapat menggunakan array karakter dan mengubahnya atau menggunakan StringBuilder.
Keluaran:
sumber
Atau Anda dapat mencoba:
Ini akan menunjukkan bagaimana kode hash berubah.
sumber
String tidak dapat diubah artinya Anda tidak dapat mengubah objek itu sendiri, tetapi Anda dapat mengubah referensi ke objek tersebut. Ketika Anda memanggil a = "ty", Anda sebenarnya mengubah referensi a ke objek baru yang dibuat oleh String literal "ty". Mengubah objek berarti menggunakan metode untuk mengubah salah satu bidangnya (atau bidang bersifat publik dan bukan final, sehingga dapat diperbarui dari luar tanpa mengaksesnya melalui metode), misalnya:
Sementara di kelas yang tidak dapat diubah (dinyatakan sebagai final, untuk mencegah modifikasi melalui pewarisan) (metodenya tidak dapat memodifikasi bidangnya, dan juga bidang selalu pribadi dan direkomendasikan untuk final), misalnya String, Anda tidak dapat mengubah String saat ini tetapi Anda dapat mengembalikan String baru, yaitu:
sumber
Di sini immutability berarti instance dapat menunjuk ke referensi lain tetapi konten asli dari string tidak akan diubah pada referensi asli. Biarkan saya jelaskan dengan contoh pertama yang Anda berikan. Str pertama menunjuk ke "Halo", ok untuk ini. Kedua kalinya menunjuk ke "Bantuan!". Di sini str mulai menunjuk ke "Tolong!" dan referensi dari string "Hello" hilang dan kami tidak bisa mendapatkannya kembali.
Bahkan ketika str akan mencoba untuk memodifikasi konten yang ada, maka string baru akan dihasilkan dan str akan mulai menunjuk pada referensi itu. Jadi kita melihat bahwa string pada referensi asli tidak dimodifikasi tetapi aman pada referensi dan contoh objek mulai menunjuk pada referensi yang berbeda sehingga ketidakmampuan dipertahankan.
sumber
Super terlambat menjawab, tetapi ingin memberikan pesan singkat dari penulis kelas String di Jawa
Dapat diturunkan dari dokumentasi ini bahwa apa pun yang mengubah string, mengembalikan objek yang berbeda (yang bisa baru atau diinternir dan lama). Petunjuk tidak begitu halus tentang ini harus berasal dari tanda tangan fungsi. Pikirkan tentang hal ini, 'Mengapa mereka membuat fungsi pada suatu objek mengembalikan sebuah objek alih-alih status?'.
Juga satu lagi sumber yang membuat perilaku ini eksplisit (Dari ganti fungsi dokumentasi)
Sumber: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char,%20char)
Sumber: JavaDoc of String.
sumber
String Obyek - metode itu sendiri dibuat menjadi "tidak berubah". Tindakan ini tidak menghasilkan perubahan: "letters.replace (" bbb "," aaa ");"
Namun penetapan data menyebabkan perubahan pada konten Strings berubah:
// Kode hash dari string Object tidak berubah.
sumber
Jika
HELLO
adalah Anda String maka Anda tidak dapat mengubahHELLO
keHILLO
. Properti ini disebut properti kekekalan.Anda dapat memiliki beberapa variabel String penunjuk ke titik String HELLO.
Tetapi jika HELLO adalah char Array maka Anda dapat mengubah HELLO menjadi HILLO. Misalnya,
Bahasa pemrograman memiliki variabel data yang tidak berubah sehingga dapat digunakan sebagai kunci dalam pasangan nilai.
sumber
Saya akan menjelaskannya dengan contoh sederhana
pada array karakter kita dapat melakukan operasi seperti mencetak hanya tiga huruf terakhir menggunakan iterating array; tetapi dalam string kita harus membuat objek String baru dan menyalin substring yang diperlukan dan alamatnya akan berada di objek string baru.
misalnya
jadi s2 akan memiliki "hel";
sumber
String di Java dalam Immutable dan Final hanya berarti tidak dapat diubah atau dimodifikasi:
Kasus 1:
Kasus 2:
sumber
Karena String tidak dapat diubah, maka perubahan tidak akan terjadi jika Anda tidak akan menetapkan nilai fungsi yang dikembalikan ke string.so di pertanyaan Anda, nilai swap fungsi nilai yang dikembalikan ke s.
s = swap (s, n1, n2); maka nilai string s akan berubah.
Saya juga mendapatkan nilai yang tidak berubah ketika saya menulis program untuk mendapatkan beberapa string permutasi (Meskipun tidak memberikan semua permutasi tetapi ini misalnya untuk menjawab pertanyaan Anda)
Berikut ini sebuah contoh.
tetapi saya tidak mendapatkan nilai-nilai permutasi string dari kode di atas. Jadi saya menetapkan nilai yang dikembalikan dari fungsi swap ke string dan mendapat nilai string yang diubah. setelah menetapkan nilai yang dikembalikan saya mendapat nilai string yang diijinkan.
sumber
Akan menghasilkan mengeluarkan sesuatu seperti ini
1419358369 1419358369
103056 65078777
Tujuan dari objek yang tidak dapat diubah adalah nilainya tidak boleh diubah begitu ditugaskan. Ini akan mengembalikan objek baru setiap kali Anda mencoba mengubahnya berdasarkan implementasi. Catatan: Stringbuffer sebagai ganti string dapat digunakan untuk menghindari hal ini.
Untuk pertanyaan terakhir Anda :: u akan memiliki satu referensi, dan 2 string dalam kumpulan string .. Kecuali referensi akan menunjuk ke m! Ss! Ss! Pp!
sumber