Saya terbiasa melakukan hal berikut dalam C
:
void main() {
String zText = "";
fillString(zText);
printf(zText);
}
void fillString(String zText) {
zText += "foo";
}
Dan hasilnya adalah:
foo
Namun, di Jawa, ini sepertinya tidak berhasil. Saya berasumsi karena String
objek disalin alih-alih dilewatkan oleh referensi . Saya pikir String adalah objek, yang selalu dilewati dengan referensi.
Apa yang terjadi disini?
java
string
pass-by-reference
Soren Johnson
sumber
sumber
Jawaban:
Anda memiliki tiga opsi:
Gunakan StringBuilder:
Buat kelas wadah dan berikan instance wadah ke metode Anda:
Buat sebuah array:
Dari sudut pandang kinerja, StringBuilder biasanya merupakan pilihan terbaik.
sumber
StringBuilder
lebih cepats += "..."
karena tidak mengalokasikan objek String baru setiap saat. Bahkan ketika Anda menulis kode Java sepertis = "Hello " + name
, maka kompiler akan menghasilkan kode byte yang membuatStringBuilder
dan memanggilappend()
dua kali.Di Jawa tidak ada yang dilewatkan dengan referensi . Semuanya dilewatkan dengan nilai . Referensi objek dilewatkan oleh nilai. Selain itu, String tidak dapat diubah . Jadi ketika Anda menambahkan ke String yang diteruskan Anda hanya mendapatkan String baru. Anda bisa menggunakan nilai balik, atau meneruskan StringBuffer sebagai gantinya.
sumber
Apa yang terjadi adalah bahwa referensi dilewatkan oleh nilai, yaitu, salinan referensi dilewatkan. Tidak ada dalam java yang dilewatkan oleh referensi, dan karena sebuah string tidak dapat diubah, tugas itu menciptakan objek string baru yang ditunjuk oleh salinan referensi tersebut . Referensi asli masih menunjuk ke string kosong.
Ini akan sama untuk objek apa pun, yaitu, menetapkannya ke nilai baru dalam suatu metode. Contoh di bawah ini hanya membuat apa yang sedang terjadi menjadi lebih jelas, tetapi menggabungkan string adalah hal yang sama.
sumber
java.lang.String tidak dapat diubah.
Saya benci menempel URL tetapi https://docs.oracle.com/javase/10/docs/api/java/lang/String.html sangat penting bagi Anda untuk membaca dan memahami jika Anda berada di java-land.
sumber
objek dilewatkan dengan referensi, primitif dilewatkan oleh nilai.
String bukan primitif, itu adalah objek, dan itu adalah kasus khusus objek.
Ini untuk tujuan penghematan memori. Di JVM, ada kumpulan string. Untuk setiap string yang dibuat, JVM akan mencoba untuk melihat apakah string yang sama ada di kumpulan string, dan arahkan ke sana jika sudah ada.
/ * OUTPUT * /
== memeriksa alamat memori (referensi), dan .equals memeriksa isi (nilai)
sumber
Semua argumen di Jawa diteruskan oleh nilai. Saat Anda melewatkan
String
fungsi, nilai yang diteruskan adalah referensi ke objek String, tetapi Anda tidak bisa mengubah referensi itu, dan objek String yang mendasarinya tidak berubah.Tugas
setara dengan:
Artinya, itu (secara lokal) menetapkan kembali parameter
zText
sebagai referensi baru, yang menunjuk ke lokasi memori baru, di mana ini adalah yang baruString
yang berisi konten aslizText
dengan"foo"
ditambahkan.Objek asli tidak dimodifikasi, dan
main()
variabel lokal metodezText
masih menunjuk ke string asli (kosong).cetakan:
Jika Anda ingin memodifikasi string, Anda dapat menggunakan
StringBuilder
atau mencatat beberapa wadah (array atauAtomicReference
kelas kontainer kustom) yang memberi Anda tingkat tipuan pointer tambahan. Atau, kembalikan nilai baru dan berikan:cetakan:
Ini mungkin solusi yang paling mirip-Java dalam kasus umum - lihat item Java yang Efektif "Fungsikan ketidakmampuan."
Seperti yang disebutkan,
StringBuilder
akan sering memberi Anda kinerja yang lebih baik - jika Anda memiliki banyak penambahan yang harus dilakukan, khususnya di dalam satu loop, gunakanStringBuilder
.Tetapi cobalah untuk melewati kekekalan
Strings
alih-alih bisa berubahStringBuilders
jika Anda bisa - kode Anda akan lebih mudah dibaca dan lebih bisa dipelihara. Pertimbangkan membuat parameter Andafinal
, dan mengkonfigurasi IDE Anda untuk memperingatkan Anda ketika Anda menetapkan kembali parameter metode ke nilai baru.sumber
String adalah objek abadi di Jawa. Anda bisa menggunakan kelas StringBuilder untuk melakukan pekerjaan yang ingin Anda capai, sebagai berikut:
Pilihan lain adalah membuat kelas dengan String sebagai variabel lingkup (sangat tidak disarankan) sebagai berikut:
sumber
Jawabannya sederhana. Dalam string java tidak berubah. Maka itu seperti menggunakan 'final' modifier (atau 'const' di C / C ++). Jadi, setelah ditugaskan, Anda tidak dapat mengubahnya seperti yang Anda lakukan.
Anda dapat mengubah yang nilai yang string poin, tetapi Anda tidak dapat mengubah nilai aktual yang string ini saat ini menunjuk.
Yaitu.
String s1 = "hey"
. Anda dapat membuats1 = "woah"
, dan itu sama sekali tidak apa-apa, tetapi Anda tidak dapat benar-benar mengubah nilai yang mendasari string (dalam hal ini: "hei") menjadi sesuatu yang lain setelah ditugaskan menggunakan plusEquals, dll. (Mis.s1 += " whatup != "hey whatup"
).Untuk melakukan itu, gunakan kelas StringBuilder atau StringBuffer atau wadah yang bisa berubah, lalu panggil saja .toString () untuk mengubah objek kembali menjadi string.
Catatan: String sering digunakan sebagai kunci hash karena itu bagian dari alasan mengapa mereka tidak dapat diubah.
sumber
=
pada referensi PERNAH memengaruhi objek yang digunakan untuk menunjuk, terlepas dari kelas.String adalah kelas khusus di Jawa. Ini adalah Thread Safe yang berarti "Setelah instance String dibuat, konten instance String tidak akan pernah berubah".
Inilah yang sedang terjadi
Pertama, kompiler Java akan mendapatkan nilai instance String zText, kemudian membuat instance String baru yang nilainya zText menambahkan "foo". Jadi, Anda tahu mengapa instance yang zText tunjuk tidak berubah. Ini benar-benar contoh baru. Bahkan, bahkan String "foo" adalah turunan String baru. Jadi, untuk pernyataan ini, Java akan membuat dua instance String, satu adalah "foo", yang lain adalah nilai zText menambahkan "foo". Aturannya sederhana: Nilai instance String tidak akan pernah berubah.
Untuk metode fillString, Anda dapat menggunakan StringBuffer sebagai parameter, atau Anda dapat mengubahnya seperti ini:
sumber
String tidak dapat diubah di Jawa.
sumber
Ini berfungsi menggunakan StringBuffer
Bahkan lebih baik gunakan StringBuilder
sumber
String tidak dapat diubah dalam java. Anda tidak dapat memodifikasi / mengubah, string literal / objek yang ada.
String s = "Hello"; s = s + "hai";
Di sini referensi sebelumnya diganti oleh referensi baru yang menunjuk ke nilai "HelloHi".
Namun, untuk menghadirkan mutabilitas, kami memiliki StringBuilder dan StringBuffer.
StringBuilder s = new StringBuilder (); s.append ("Hai");
ini menambahkan nilai baru "Hai" ke referensi yang sama. //
sumber
Aaron Digulla memiliki jawaban terbaik sejauh ini. Variasi dari opsi keduanya adalah menggunakan kelas pembungkus atau wadah MutableObject dari commons lang library versi 3+:
Anda menyimpan deklarasi kelas kontainer. Kekurangannya adalah ketergantungan pada comm lun lib. Tetapi lib memiliki cukup banyak fungsi yang berguna dan hampir semua proyek besar yang saya kerjakan menggunakannya.
sumber
Untuk melewati objek (termasuk String) dengan referensi di java, Anda mungkin meneruskannya sebagai anggota adaptor di sekitarnya. Solusi dengan obat generik ada di sini:
sumber
Untuk seseorang yang lebih penasaran
sumber