Ini bisa menjadi pertanyaan terbodoh yang pernah meminta, tapi saya pikir hal ini cukup membingungkan untuk Java pemula.
String
berubah?StringBuilder
lebih disukai String dan wakil-ayat?Contoh yang bagus (di Jawa) akan benar-benar dihargai.
Berubah berarti bahwa sekali konstruktor untuk sebuah objek telah melengkapi verifikasi identitas eksekusi itu misalnya dapat't dapat diubah.
Hal ini berguna seperti itu berarti anda dapat melewati referensi ke objek sekitar, tanpa khawatir bahwa orang lain akan berubah isinya. Terutama ketika berhadapan dengan concurrency, tidak ada penguncian masalah dengan benda-benda yang tidak pernah berubah
misalnya
class Foo
{
private final String myvar;
public Foo(final String initialValue)
{
this.myvar = initialValue;
}
public String getValue()
{
return this.myvar;
}
}
Foo
doesn't perlu khawatir bahwa penelepon untuk getValue()
mungkin mengubah teks dalam string.
Jika anda membayangkan kelas yang sama untuk Foo
, tapi dengan StringBuilder
daripada String
sebagai anggota, anda dapat melihat bahwa penelepon untuk getValue()
akan mampu mengubah StringBuilder
atribut Foo
misalnya.
Juga berhati-hatilah dari berbagai jenis ketetapan yang mungkin anda cari: Eric Lippert menulis artikel blog tentang hal ini. Pada dasarnya anda dapat memiliki benda-benda dan antarmuka berubah tapi di belakang layar sebenarnya mutables private negara (dan oleh karena itu dapat't dibagi dengan aman antara benang).
Abadi objek adalah objek di mana bidang-bidang internal (atau setidaknya, semua bidang-bidang internal yang mempengaruhi perilaku eksternal) tidak dapat diubah.
Ada banyak keuntungan untuk berubah string:
Kinerja: Mengambil operasi berikut:
String substring = fullstring.substring(x,y);
Yang mendasari C untuk substring() metode ini mungkin sesuatu seperti ini:
// Assume string is stored like this:
struct String { char* characters; unsigned int length; };
// Passing pointers because Java is pass-by-reference
struct String* substring(struct String* in, unsigned int begin, unsigned int end)
{
struct String* out = malloc(sizeof(struct String));
out->characters = in->characters + begin;
out->length = end - begin;
return out;
}
Perhatikan bahwa tidak ada karakter yang akan disalin! Jika String obyek yang bisa berubah (karakter bisa berubah nanti) maka anda akan memiliki untuk menyalin semua karakter, jika tidak, perubahan karakter substring akan tercermin dalam string lain nanti.
Concurrency: Jika struktur internal abadi objek adalah valid, hal ini akan selalu berlaku. Ada's tidak ada kesempatan bahwa benang yang berbeda dapat menciptakan keadaan yang tidak sah dalam objek itu. Oleh karena itu, abadi benda BenangAman.
Pengumpulan sampah: It's jauh lebih mudah untuk pengumpul sampah untuk membuat keputusan yang logis tentang benda berubah.
Namun, ada juga kerugian untuk kekekalan:
Kinerja: Tunggu, saya pikir anda mengatakan kinerja terbalik dari kekekalan! Nah, kadang-kadang, tapi tidak selalu. Mengambil kode berikut:
foo = foo.substring(0,4) + "a" + foo.substring(5); // foo is a String
bar.replace(4,5,"a"); // bar is a StringBuilder
Dua baris kedua menggantikan karakter keempat dengan huruf "a". Tidak hanya adalah bagian kedua dari kode lebih mudah dibaca, it's lebih cepat. Lihat bagaimana anda akan harus melakukan yang mendasari kode untuk foo. Yang substring yang mudah, tapi sekarang karena ada's sudah karakter di ruang lima dan sesuatu yang lain yang dapat menjadi referensi foo, anda dapat't hanya mengubah itu, anda harus menyalin seluruh string (tentu saja beberapa dari fungsi ini disarikan ke fungsi yang sebenarnya mendasari C, tapi intinya di sini adalah untuk menunjukkan kode yang akan dieksekusi di satu tempat).
struct String* concatenate(struct String* first, struct String* second)
{
struct String* new = malloc(sizeof(struct String));
new->length = first->length + second->length;
new->characters = malloc(new->length);
int i;
for(i = 0; i < first->length; i++)
new->characters[i] = first->characters[i];
for(; i - first->length < second->length; i++)
new->characters[i] = second->characters[i - first->length];
return new;
}
// The code that executes
struct String* astring;
char a = 'a';
astring->characters = &a;
astring->length = 1;
foo = concatenate(concatenate(slice(foo,0,4),astring),slice(foo,5,foo->length));
Perhatikan bahwa menggabungkan dipanggil dua kali yang berarti bahwa seluruh string harus dilingkarkan melalui! Bandingkan ini dengan kode C untuk bar
operasi:
bar->characters[4] = 'a';
Bisa berubah string operasi ini jelas jauh lebih cepat.
Kesimpulan: Dalam kebanyakan kasus, anda ingin berubah string. Tapi jika anda perlu untuk melakukan banyak menambahkan dan memasukkan ke dalam string, anda perlu berubah-ubah untuk kecepatan. Jika anda ingin concurrency keselamatan dan pengumpulan sampah manfaat dengan itu kuncinya adalah untuk menjaga benda-benda yang bisa berubah lokal untuk metode:
// This will have awful performance if you don't use mutable strings
String join(String[] strings, String separator)
{
StringBuilder mutable;
boolean first = true;
for(int i = 0; i < strings.length; i++)
{
if(!first) first = false;
else mutable.append(separator);
mutable.append(strings[i]);
}
return mutable.toString();
}
Karena berubah
objek referensi lokal, anda don't perlu khawatir tentang concurrency keselamatan (hanya satu thread yang pernah menyentuhnya). Dan sejak itu isn't direferensikan di tempat lain, itu hanya dialokasikan pada stack, sehingga deallocated sesegera fungsi panggilan selesai (anda don't perlu khawatir tentang pengumpulan sampah). Dan anda mendapatkan semua manfaat kinerja dari kedua berubah-ubah dan kekekalan.
Sebenarnya String tidak berubah jika anda menggunakan wikipedia definisi yang disarankan di atas.
String's keadaan tidak berubah pasca konstruksi. Lihatlah kode hash() metode. String cache kode hash value di lapangan lokal tetapi tidak menghitung itu sampai panggilan pertama dari kode hash(). Ini malas evaluasi kode hash String di tempat-tempat yang menarik posisi sebagai abadi objek dan perubahan negara, tetapi tidak dapat diamati telah berubah tanpa menggunakan refleksi.
Jadi mungkin definisi harus berubah menjadi sebuah objek yang tidak dapat diamati telah berubah.
Jika negara perubahan abadi objek setelah telah dibuat tetapi tidak ada yang dapat melihatnya (tanpa pantulan) adalah objek masih berubah?
Abadi benda-benda yang benda-benda yang dapat't diubah pemrograman. Mereka're sangat baik untuk multi-threaded lingkungan atau lingkungan lain di mana lebih dari satu proses yang dapat mengubah (bermutasi) nilai-nilai dalam suatu objek.
Hanya untuk memperjelas, namun, StringBuilder sebenarnya adalah sebuah obyek bisa berubah, tidak berubah satu. Reguler jawa String adalah kekal (yang berarti bahwa setelah itu's telah dibuat anda tidak dapat mengubah mendasari string tanpa mengubah objek).
Misalnya, let's mengatakan bahwa saya memiliki kelas yang disebut ColoredString yang memiliki nilai String dan String warna:
public class ColoredString {
private String color;
private String string;
public ColoredString(String color, String string) {
this.color = color;
this.string = string;
}
public String getColor() { return this.color; }
public String getString() { return this.string; }
public void setColor(String newColor) {
this.color = newColor;
}
}
Dalam contoh ini, ColoredString dikatakan bisa berubah karena anda dapat berubah (bermutasi) salah satu sifat kunci tanpa membuat baru ColoredString kelas. Alasan mengapa hal ini dapat berakibat buruk, misalnya, let's katakanlah anda memiliki sebuah aplikasi GUI yang memiliki beberapa benang dan anda menggunakan ColoredStrings untuk mencetak data ke jendela. Jika anda memiliki contoh ColoredString yang diciptakan sebagai
new ColoredString("Blue", "This is a blue string!");
Kemudian anda akan mengharapkan string untuk selalu "Blue". Jika thread lain, bagaimanapun, mendapat kuasai hal ini dan disebut
blueString.setColor("Red");
Anda akan tiba-tiba, dan mungkin secara tiba-tiba, sekarang memiliki "Red" string ketika anda ingin "Blue" satu. Karena ini, abadi benda-benda yang hampir selalu disukai ketika lewat contoh-contoh benda-benda di sekitar. Bila anda memiliki kasus di mana bisa berubah benda yang benar-benar diperlukan, maka anda biasanya akan menjaga objet dengan hanya lewat salinan keluar dari bidang tertentu dari kontrol.
Untuk rekap, di Jawa, di jawa.lang.String adalah abadi objek (ini tidak akan berubah setelah itu's dibuat) dan jawa.lang.StringBuilder adalah sebuah obyek bisa berubah karena dapat berubah tanpa membuat instance baru.
String s1 = "string Tua";
//s1 variable, refers to string in memory
reference | MEMORY |
variables | |
[s1] --------------->| "Old String" |
String s2 = s1;
//s2 refers to same string as s1
| |
[s1] --------------->| "Old String" |
[s2] ------------------------^
s1 = "String Baru";
//s1 deletes reference to old string and points to the newly created one
[s1] -----|--------->| "New String" |
| | |
|~~~~~~~~~X| "Old String" |
[s2] ------------------------^
asli string 'di memori' aku't perubahan, tetapi referensi variabel berubah sehingga hal ini mengacu pada string baru. Dan jika kita tidak't memiliki s2, "String Tua" masih akan berada di memori tapi kami'll tidak dapat mengaksesnya...
"berubah" berarti anda tidak dapat mengubah nilai. Jika anda memiliki sebuah instance dari class String, apapun metode yang anda panggilan yang tampaknya untuk mengubah nilai, benar-benar akan membuat String lain.
String foo = "Hello";
foo.substring(3);
<-- foo here still has the same value "Hello"
Untuk melestarikan perubahan anda harus melakukan sesuatu seperti ini foo = foo.sustring(3);
Abadi vs mutable bisa lucu ketika anda bekerja dengan koleksi. Pikirkan tentang apa yang akan terjadi jika anda menggunakan mutable objek sebagai kunci untuk peta dan kemudian mengubah nilai (tip: berpikir tentang sama dengan
dan kode hash
).
Mungkin sedikit terlambat, tapi dalam rangka untuk memahami apa yang berubah objek, perhatikan contoh berikut dari baru Jawa 8 Tanggal dan Waktu API (jawa.waktu). Seperti anda mungkin tahu semua benda-benda dari tanggal Jawa 8 abadi jadi dalam contoh berikut
LocalDate date = LocalDate.of(2014, 3, 18);
date.plusYears(2);
System.out.println(date);
Output:
2014-03-18
Ini cetakan tahun yang sama sebagai tanggal awal karena plusYears(2)
mengembalikan sebuah objek baru jadi tanggal tua masih tidak berubah karena itu's berubah obyek. Begitu dibuat, anda tidak dapat lagi mengubah hal itu dan tanggal variabel masih poin untuk itu.
Jadi, itu contoh kode harus menangkap dan menggunakan objek baru diturunkan dan kembali dengan panggilan itu untuk plusYears
.
LocalDate date = LocalDate.of(2014, 3, 18);
LocalDate dateAfterTwoYears = date.plusYears(2);
upload.toString()... 2014-03-18
dateAfterTwoYears.toString()... 2016-03-18
Aku benar-benar seperti penjelasan dari SCJP Matahari Bersertifikat Java Programmer untuk 5 Panduan Belajar.
Untuk membuat Jawa memori yang lebih efisien, JVM menyisihkan khusus area memori yang disebut "String constant pool." Ketika compiler pertemuan String literal, ia memeriksa outdoor untuk melihat apakah identik String yang sudah ada. Jika kecocokan ditemukan, referensi baru literal diarahkan untuk ada String, dan tidak ada String literal objek dibuat.
Benda-benda yang berubah tidak dapat memiliki negara mereka berubah setelah mereka telah dibuat.
Ada tiga alasan utama untuk menggunakan benda berubah setiap kali anda bisa, semua yang akan membantu untuk mengurangi jumlah bug anda memperkenalkan dalam kode anda:
Ada juga beberapa optimisations anda mungkin dapat membuat dalam kode ketika anda tahu bahwa state dari sebuah objek adalah berubah - caching hash dihitung, misalnya - tapi ini adalah pengoptimalan dan oleh karena itu hampir tidak begitu menarik.
Salah satu makna yang ada hubungannya dengan bagaimana nilai tersebut disimpan dalam komputer, Untuk .Net string misalnya, itu berarti bahwa string dalam memori tidak dapat diubah, Ketika anda berpikir anda're mengubah itu, anda sebenarnya membuat sebuah string dalam memori dan menunjuk variabel yang ada (yang hanya pointer untuk koleksi yang sebenarnya dari karakter di tempat lain) untuk string baru.
String s1="Hi";
String s2=s1;
s1="Bye";
System.out.println(s2); //Hi (if String was mutable output would be: Bye)
System.out.println(s1); //Bye
s1="Hi"
: sebuah objek s1
diciptakan dengan "Hi" nilai di dalamnya.
s2=s1
: sebuah objek s2
dibuat dengan mengacu s1 objek.
s1="Tinggal"
: sebelumnya s1
objek's nilai doesn't perubahan, karena s1
memiliki tipe String dan String tipe ini berubah jenis, bukan compiler membuat objek String dengan "Tinggal" nilai dan s1
direferensikan untuk itu. di sini ketika kami mencetak s2
nilai, hasilnya akan menjadi "Hi" tidak "Tinggal" karena s2
direferensikan sebelumnya s1
objek yang memiliki "Hi" nilai.
Yang tak berubah hanya berarti tidak dapat diubah atau unmodifiable. Setelah string objek dibuat data atau negara dapat't diubah
Perhatikan contoh di bawah,
class Testimmutablestring{
public static void main(String args[]){
String s="Future";
s.concat(" World");//concat() method appends the string at the end
System.out.println(s);//will print Future because strings are immutable objects
}
}
Let's mendapatkan ide mengingat di bawah diagram,
Dalam diagram ini, anda bisa melihat objek baru diciptakan sebagai "masa Depan Dunia". Tapi tidak mengubah "masa Depan".Karena String adalah kekal
. s
, masih mengacu pada "masa Depan". Jika anda perlu untuk memanggil "masa Depan Dunia",
String s="Future";
s=s.concat(" World");
System.out.println(s);//print Future World
Mengapa objek string yang berubah di jawa?
Karena Java menggunakan konsep string literal. Misalkan ada 5 referensi variabel, semua mengacu pada satu objek "masa Depan".Jika salah satu referensi variabel perubahan nilai dari objek, maka akan mempengaruhi semua referensi variabel. Itulah sebabnya objek string yang berubah di jawa.
Berubah berarti bahwa sekali objek dibuat, non anggotanya akan berubah. String
adalah kekal karena anda tidak dapat mengubah isinya.
Misalnya:
String s1 = " abc ";
String s2 = s1.trim();
Dalam kode di atas, string s1 tidak berubah, objek lain (s2
) dibuat menggunakan s1
.
Abadi Benda
Sebuah objek dianggap berubah jika keadaan tidak berubah setelah itu dibangun. Maksimum ketergantungan pada benda berubah secara luas diterima sebagai strategi untuk menciptakan sederhana, kode yang dapat diandalkan.
Abadi benda-benda yang sangat berguna dalam aplikasi bersamaan. Karena mereka tidak bisa mengubah keadaan, mereka tidak dapat rusak oleh benang gangguan atau diamati dalam keadaan yang tidak konsisten.
Programmer sering enggan untuk mempekerjakan abadi benda, karena mereka khawatir tentang biaya membuat objek baru sebagai lawan untuk memperbarui sebuah objek di tempat. Dampak dari pembuatan obyek ini sering berlebihan, dan dapat diimbangi oleh beberapa efisiensi yang berhubungan dengan benda berubah. Ini termasuk penurunan overhead karena untuk pengumpulan sampah, dan penghapusan kode yang dibutuhkan untuk melindungi benda-benda yang bisa berubah dari korupsi.
Berikut subbagian mengambil kelas dan contoh yang bisa berubah dan berasal kelas dengan berubah contoh dari itu. Dengan begitu, mereka memberikan aturan umum untuk jenis konversi dan menunjukkan beberapa keuntungan dari benda berubah.
Abadi objek adalah salah satu yang anda tidak dapat memodifikasi setelah anda membuat itu. Sebuah contoh khas adalah string literal.
D bahasa pemrograman, yang menjadi semakin populer, memiliki gagasan "ketetapan" melalui "lain" kata kunci. Cek ini Dr Dobb's artikel tentang itu - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29 . Ini menjelaskan masalah dengan sempurna.