2012-12-10 14 views
13

Olası Çoğalt:
What is the purpose of the expression “new String(…)” in Java?Neden String sınıfı kopya oluşturucusu var?

değişmez sınıflar kopyalar orijinal eşit olacağını itiraz eden olursa o zaman neden Java String sınıf bir kopya kurucu var? Bu bir hata mı yoksa bu uygulamanın arkasında bir neden var mı? Java docs yılında o belirtilir:

/** 
* Initializes a newly created {@code String} object so that it represents 
* the same sequence of characters as the argument; in other words, the 
* newly created string is a copy of the argument string. Unless an 
* explicit copy of {@code original} is needed, use of this constructor is 
* unnecessary since Strings are immutable. 
* 
* @param original 
*   A {@code String} 
*/ 
public String(String original) { 
.... 
....} 
+6

Bu "çok yerelleştirilmiş" değil, daha sonra yararlı ve bilgilendirici bir yanıtla bulanlar için geçerli iyi bir soru. –

+3

Bkz. [This] (http://stackoverflow.com/a/465682/1037210) yanıtı. – Lion

+0

Belirtilen benzer soruya verilen cevapların artık artık eskimiş olduğu düşünülebilir. –

cevap

10

bir dize etmektir kopyalamak için ana nedeni "bagajı Döşeme", bu gerekli tek şeydir etmek yatan Char dizi Döşeme etmektir.

Temel char dizisi temel olarak çok büyük olabilir, çünkü substring numaralı telefonu arayarak bir dize oluşturduğunuzda, char dizisi yeni dize örneği ile kaynak dize örneği arasında paylaşılabilir; İlk karaktere bir ofset noktası ve uzunluk dahildir.

164  public String(String original) { 
    165   int size = original.count; 
    166   char[] originalValue = original.value; 
    167   char[] v; 
    168   if (originalValue.length > size) { 
    169    // The array representing the String is bigger than the new 
    170    // String itself. Perhaps this constructor is being called 
    171    // in order to trim the baggage, so make a copy of the array. 
    172    int off = original.offset; 
    173    v = Arrays.copyOfRange(originalValue, off, off+size); 
    174   } else { 
    175    // The array representing the String is the same 
    176    // size as the String, so no point in making a copy. 
    177    v = originalValue; 
    178   } 
    179   this.offset = 0; 
    180   this.count = size; 
    181   this.value = v; 

Bu, birçok geliştiriciler unutmak bir şeydir ve küçük bir dize önleyebilir çünkü önemlidir:

ifadesi Ben "bagajı Döşeme", kullanmak, dize kopyalama yapıcı kaynak kodundan alınır Daha büyük bir char dizisinin garbaglanması. Bunu zaten işaret ettiğim bu ilgili soruya bakın: Java not garbage collecting memory. Birçok geliştirici, Java tasarımcılarının C kodlayıcılarına aşina olan bu eski optimizasyon hilesini kullanması kararından ziyade, iyi olandan daha fazla zarar verdiğini düşünmektedir. Birçoğumuz bunu biliyoruz çünkü biz bunun tarafından ısırıldık ve ne olduğunu anlamak için Sun'ın kaynak koduna bakmak zorunda kaldık ...

Marko işaret ettiğinden (aşağıdaki yorumlara bakın), OpenJDK'de, java 7'den başlayarak 6 Güncelleme 6 , substring artık char dizisini paylaşmıyor ve String(String) yapıcı, dolayısıyla, işe yaramaz. Ama yine de hızlıdır (aslında daha hızlıdır) ve bu değişiklik tüm VM'ye (ve muhtemelen tüm müşterilerinize) yayılmadığından, eski davranışını haklı çıkarırken bu en iyi uygulamayı new String(substring)'u kullanmaya devam etmenizi tavsiye ederim. .

+5

... ve OpenJDK 7, Güncelleme 6'dan itibaren yok. Altyapı, trim vb. Ile daha fazla yapısal paylaşım yok. –

+0

@Marko Bahsettiğiniz güncellemenin kaynağını işaret edebilir misiniz? Bu önemli değişimin farkında değildim. –

+3

[Buraya referans] (http://hg.openjdk.java.net/jdk7u/jdk7u6/jdk/file/8c2c5d63a17e/src/share/classes/java/lang/String.java) Zaten onu favorilere ekledim, Jon Skeet'ten öğrendiğimden beri popüler bir taleptim! –

İlgili konular