Mengapa String Tidak Boleh Diubah di Jawa?

1. Pengenalan

Di Jawa, String tidak berubah. Pertanyaan jelas yang cukup lazim dalam wawancara adalah "Mengapa String dirancang sebagai tidak berubah di Java?"

James Gosling, pencipta Java, pernah ditanya dalam wawancara kapan harus menggunakan orang yang tidak berubah, yang dia jawab:

Saya akan menggunakan yang tidak berubah setiap kali saya boleh.

Dia lebih jauh menyokong hujahnya yang menyatakan ciri-ciri yang tidak dapat diubah, seperti cache, keselamatan, penggunaan semula yang mudah tanpa replikasi, dll

Dalam tutorial ini, kita akan menerangkan lebih lanjut mengapa pereka bahasa Java memutuskan untuk mengekalkan String tidak berubah.

2. Apakah Objek yang Tidak Berubah?

Objek yang tidak berubah adalah objek yang keadaan dalamannya tetap berterusan setelah ia diciptakan sepenuhnya . Ini bermaksud bahawa setelah objek ditugaskan ke variabel, kita tidak dapat memperbarui rujukan atau mengubah keadaan dalaman dengan cara apa pun.

Kami mempunyai artikel berasingan yang membincangkan objek yang tidak berubah secara terperinci. Untuk maklumat lebih lanjut, baca artikel Objek Tidak Berubah di Java.

3. Mengapa String Tidak Boleh Diubah di Jawa?

Manfaat utama menjadikan kelas ini tidak berubah adalah cache, keselamatan, penyegerakan, dan prestasi.

Mari kita bincangkan bagaimana perkara ini berfungsi.

3.1. Perkenalkan ke String Pool

The String adalah struktur data yang paling banyak digunakan. Cache yang String literal dan menggunakan semula mereka menjimatkan banyak ruang timbunan kerana berbeza String pembolehubah merujuk kepada objek yang sama dalam String kolam. String intern pool berfungsi dengan tepat untuk tujuan ini.

Java String Pool ialah rantau memori khas di mana Strings disimpan oleh JVM . Oleh kerana Strings tidak dapat diubah di Java, JVM mengoptimumkan jumlah memori yang diperuntukkan untuk mereka dengan menyimpan hanya satu salinan setiap String literal di kumpulan. Proses ini dipanggil interning:

String s1 = "Hello World"; String s2 = "Hello World"; assertThat(s1 == s2).isTrue();

Kerana kehadiran kumpulan String dalam contoh sebelumnya, dua pemboleh ubah yang berbeza menunjuk ke objek String yang sama dari kolam, sehingga menjimatkan sumber memori penting.

Kami mempunyai artikel terpisah yang dikhaskan untuk Java String Pool. Untuk maklumat lebih lanjut, baca artikel itu.

3.2. Keselamatan

The String digunakan secara meluas dalam aplikasi Java untuk menyimpan keping sensitif maklumat seperti nama pengguna, kata laluan, URL sambungan, sambungan rangkaian, dan lain-lain Ia juga digunakan secara meluas oleh Pemuat kelas JVM manakala kelas loading.

Oleh itu, keselamatan kelas String sangat penting mengenai keselamatan keseluruhan aplikasi secara amnya. Sebagai contoh, pertimbangkan coretan kod ringkas ini:

void criticalMethod(String userName) { // perform security checks if (!isAlphaNumeric(userName)) { throw new SecurityException(); } // do some secondary tasks initializeDatabase(); // critical task connection.executeUpdate("UPDATE Customers SET Status = 'Active' " + " WHERE UserName = '" + userName + "'"); }

Dalam coretan kod di atas, katakan bahawa kami menerima objek String dari sumber yang tidak boleh dipercayai. Kami melakukan semua pemeriksaan keselamatan yang diperlukan pada mulanya untuk memeriksa sama ada String hanya berbentuk alfanumerik, diikuti oleh beberapa operasi lagi.

Ingat bahawa kaedah pemanggil sumber kami yang tidak boleh dipercayai masih merujuk kepada objek userName ini .

Sekiranya Strings dapat diubah, maka pada saat kami melakukan pembaruan, kami tidak dapat memastikan bahawa String yang kami terima, walaupun setelah melakukan pemeriksaan keselamatan, akan aman. Kaedah pemanggil yang tidak boleh dipercayai masih mempunyai rujukan dan dapat mengubah String antara pemeriksaan integriti. Oleh itu, membuat pertanyaan kami terdedah kepada suntikan SQL dalam kes ini. Strings yang boleh diubah boleh menyebabkan keselamatan merosot dari masa ke masa.

Ia juga boleh berlaku bahawa String userName dapat dilihat pada thread lain, yang kemudian dapat mengubah nilainya setelah pemeriksaan integriti.

Secara amnya, kebolehubahan dapat dilakukan dalam kes ini kerana lebih mudah dikendalikan dengan kod sensitif apabila nilai tidak berubah kerana terdapat sedikit interleavings operasi yang mungkin mempengaruhi hasilnya.

3.3. Penyegerakan

Menjadi tidak berubah secara automatik menjadikan benang String selamat kerana mereka tidak akan diubah ketika diakses dari beberapa utas.

Oleh itu , objek yang tidak berubah, secara amnya, dapat dikongsi di pelbagai benang yang berjalan serentak. Mereka juga thread selamat kerana jika thread yang menukar nilai, kemudian bukan mengubah suai yang sama, baru String akan diwujudkan dalam String kolam. Oleh itu, String selamat untuk multi-threading.

3.4. Hashcode Caching

Sejak String objek yang banyak digunakan sebagai struktur data, ia juga digunakan secara meluas dalam pelaksanaan hash seperti HashMap , HashTable , HashSet , dan lain-lain Apabila terhadap Orang ini pelaksanaan hash, Kodcincang () kaedah dipanggil agak kerap untuk pembrokeran liar.

Ketidakstabilan menjamin Strings bahawa nilainya tidak akan berubah. Oleh itu kaedah hashCode () diganti dalam kelas String untuk memudahkan caching, sehingga hash dikira dan di-cache semasa panggilan hashCode () pertama dan nilai yang sama dikembalikan sejak itu.

Ini seterusnya meningkatkan prestasi koleksi yang menggunakan implementasi hash ketika dikendalikan dengan objek String .

Sebaliknya, yg mungkin berubah Strings akan menghasilkan dua hashcodes yang berbeza pada masa kemasukan dan dapatan semula jika kandungan String telah diubahsuai selepas pembedahan, berpotensi kehilangan objek nilai dalam Peta .

3.5. Persembahan

Seperti yang kita lihat sebelumnya, kolam String wujud kerana Strings tidak berubah. Pada gilirannya, ia meningkatkan prestasi dengan menyimpan memori timbunan dan akses pelaksanaan hash yang lebih pantas ketika dikendalikan dengan Strings.

Oleh kerana String adalah struktur data yang paling banyak digunakan, peningkatan prestasi String mempunyai pengaruh yang cukup besar untuk meningkatkan prestasi keseluruhan aplikasi secara umum.

4. Kesimpulan

Melalui artikel ini, kita dapat menyimpulkan bahawa String tidak dapat diubah dengan tepat sehingga rujukannya dapat dianggap sebagai pemboleh ubah biasa dan seseorang dapat menyebarkannya di sekitar, antara kaedah dan merentasi benang, tanpa perlu risau sama ada objek String sebenarnya yang ditunjuknya akan berubah.

Kami juga belajar apa mungkin alasan lain yang mendorong pereka bahasa Java menjadikan kelas ini tidak berubah.