Java dize gerçekten değişmez mi?
Hepimiz String
Java değişmez ama aşağıdaki kodu kontrol edin.
String s1 = "Hello World";
String s2 = "Hello World";
String s3 = s1.substring(6);
System.out.println(s1); // Hello World
System.out.println(s2); // Hello World
System.out.println(s3); // World
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char[] value = (char[])field.get(s1);
value[6] = 'J';
value[7] = 'a';
value[8] = 'v';
value[9] = 'a';
value[10] = '!';
System.out.println(s1); // Hello Java!
System.out.println(s2); // Hello Java!
System.out.println(s3); // World
Niye bu program bu şekilde çalışır? Ve neden s1
s2
değeri, ancak s3
değiştirilmedi?
CEVAP
String
değişmez* ancak kamu API kullanarak değiştiremezsiniz Bu sadece anlamına gelir.
Burada ne yaptığını normal API, yansıma kullanarak engellemeyi. Aynı şekilde, çeteleler değerleri değiştirebilirsiniz, arama tablosu Tamsayı vb autoboxing kullanılan değiştirin.
Şimdi, s1
s2
değeri değiştir sebebi, ikisi de aynı staj dize bakın. Derleyici bu canlılar tarafından belirtildiği gibi).
Nedeni s3
yapardeğilvalue
dizi (Java 7u6 önceit did in earlier version of Java,) paylaşım olacağını düşündüm. aslında bana biraz şaşırtıcı oldu. Ancak, String
, biz kaynak kodu bakarak bir dize için value
karakter dizisi aslında (Arrays.copyOfRange(..)
) kullanarak kopyalanan görebilir. Bu değişmeden gidiyor nedeni budur.
Böyle şeyler yapmak için SecurityManager
, önlemek için kötü amaçlı kod yükleyebilir. Ama bazı kütüphaneler yansıma hileler bu tür kullanarak bağlı olduğunu göz önünde tutmak (genellikle ORM araçları OLANLAR kütüphaneleri gibi).
*) Ben başlangıçta String
s gerçekten değişmez, sadece olmadığını yazdı "değişmez". etkili Bu value
dizi gerçekten private final
işaretli olduğu String
, geçerli uygulama yanıltıcı olabilir. Hala dikkati çekiyor, ama orada hiçbir şekilde beyan bir dizi Java olarak değişmez, yani sağlık için değil, maruz dışında kendi sınıfı ile uygun erişim değiştiricileri.
Bu konu gibi ezici bir çoğunlukla popüler, İşte bazı önerilen ek okuma: Heinz Kabutz's Reflection Madness talk JavaZone 2009, kapakları bir çok konularda OP ile birlikte diğer yansıması... delilik.
Bu bazen yararlıdır neden kapsar. Ve çoğu zaman neden, bunu önlemek. :-)
Neden char[] şifreler için Dize Java t...
Java ile bir numaralama için bir Dize ...
Nasıl bir dosyanın içeriğini bir Java ...
Java nasıl bir dize bölmek...
Olabilirdi vs Dize birleştirme StringB...