Java'da Dizeleri nasıl kopyalamalıyım?


199
    String s = "hello";
    String backup_of_s = s;
    s = "bye";

Bu noktada, yedekleme değişkeni hala orijinal "merhaba" değerini içerir (bunun nedeni String'in değişmezlik hakkıdır?).

Ancak Dizeleri bu yöntemle kopyalamak gerçekten güvenli mi (elbette düzenli değiştirilebilir nesneleri kopyalamak güvenli değildir) veya bunu yazmak daha mı iyidir? :

    String s = "hello";
    String backup_of_s = new String(s);
    s = "bye";

Başka bir deyişle, bu iki parçacık arasındaki (varsa) fark nedir?


EDIT - ilk snippet'in güvenli olmasının nedeni:

Önceden verilen iyi cevaplara dayanarak (biraz daha ayrıntılı olarak açıklayayım) (esasen 2 snippet arasındaki performans farkı sorununa odaklandı):

Dizeler Java'da değiştirilemez, yani bir String nesnesinin yapıldıktan sonra değiştirilemeyeceği anlamına gelir. Bu nedenle,

String s = "hello";yeni bir String örneği oluşturur ve adresini atar s( sörneğe / nesneye başvuru olarak)

String backup_of_s = s;yeni bir değişken oluşturur backup_of_sve o anda başvurduğu nesneye referans verecek şekilde onu başlatır s.

Not: Dize değişmezliği, bu nesnenin değiştirilmeyeceğini garanti eder: yedeklememiz güvenlidir

Not 2: Java çöp toplama mekanizması, bu nesnenin en az bir değişken tarafından başvurulduğu sürece yok edilmeyeceğini garanti eder ( backup_of_sbu durumda)

Son olarak, s = "bye";başka bir String örneği oluşturur (değişmezlik nedeniyle, tek yol budur) ve sdeğişkeni, şimdi yeni nesneye başvuracak şekilde değiştirir .

Yanıtlar:


141

Dizeler değiştirilemez olduğundan, her iki sürüm de güvenlidir. Bununla birlikte, ikincisi daha az verimlidir (ekstra bir nesne oluşturur ve bazı durumlarda karakter verilerini kopyalar).

Bunu göz önünde bulundurarak, ilk sürüm tercih edilmelidir.


15
Değişmezliğin bununla hiçbir ilgisi yoktur. Nesne referansları bu şekilde çalışır. Eşdeğer bir StringBuilder örneği sağlayabilir.
GriffeyDog

1
@BalusC, nasıl yeni String () JVM String havuzunda bir şey oluşturabilir göremiyorum. Sadece string litterals ve intern () ile havuza taahhüt edilenler havuzdadır.
Snicolas

3
@GriffeyDog: Soruyu daha az anlamıyla okuyorum. Ne diyorsun birisi dizeyi değiştirmek korkusu olmadan bir dize nesnesine başvurular vermek güvenli olmasıdır.
NPE

2
@GriffeyDog Yorumunuzu çok yanıltıcı buluyorum: değişmezlik, ilk pasajı güvenli kılan şeydir, neden "bu" ile ilgisi yoktur?
Sébastien

5
@Sebastien Tüm yaptığı, referans değişkenini sfarklı bir nesneye ( String"güle") atıfta bulunmak üzere yeniden atamaktır . Bu, başvuru değişkeninin ne anlama geldiğini etkilemez backup_of_s( String"merhaba"). I sözü geçen gibi, bir eşdeğer bir örnek sağlayabilir StringBuilders, olmadığında değişmez. Benim yorum esas olarak OPs deyimi ile ilgilidir: Bu noktada, yedekleme değişkeni hala orijinal "merhaba" değerini içerir (bunun nedeni String'in değişmezlik hakkı?).
GriffeyDog

22

Dizeler değişmez nesnelerdir, bu nedenle başvurulan nesneyi değiştirerek kopyalayabilirsiniz, çünkü başvurulan nesne değişemez ...

Böylece ilk örneğinizdeki gibi herhangi bir sorun olmadan kopyalayabilirsiniz:

String s = "hello";
String backup_of_s = s;
s = "bye";

10

İkinci sürümünüz daha az verimlidir, çünkü buna gerek olmadığında fazladan bir dize nesnesi oluşturur.

Değişmezlik, ilk sürümünüzün beklediğiniz şekilde davrandığı ve bu nedenle tercih edilecek yaklaşım olduğu anlamına gelir.


0

İkinci durum da String havuzu açısından verimsizdir, staj yapmak için dönüş referansında açıkça intern () öğesini çağırmanız gerekir.


-16
String str1="this is a string";
String str2=str1.clone();

Bunun gibi bir kopyaya ne dersin? Yeni bir kopya almanın daha iyi olduğunu düşünüyorum, böylece referans str1olduğunda str2ve daha fazla eylemde değişiklik yapıldığında verilerin etkilenmeyecektir .


3
Stringdeğişmez. Dizeleri kopyalamak pek mantıklı değil.
Vladimir
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.