2012-12-10 14 views
13

Powiel możliwe:
What is the purpose of the expression “new String(…)” in Java?Dlaczego klasa String ma konstruktora kopiowania?

Jeśli Klasy niezmienne obiektów kopie byłaby równa oryginałów to dlaczego klasa w Javie String mieć konstruktor kopiujący? Czy to pomyłka, czy jest jakiś powód takiego wdrożenia? W docs Java określono, że:

/** 
* 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

To nie jest "zbyt zlokalizowane", jest to dobre pytanie dla osób znajdujących się później, z bardzo przydatną i informacyjną odpowiedzią. –

+3

Zobacz odpowiedź [this] (http://stackoverflow.com/a/465682/1037210). – Lion

+0

Należy zauważyć, że odpowiedzi na wyżej wymienione podobne pytanie można prawdopodobnie uznać za częściowo przestarzałe. –

Odpowiedz

10

Głównym powodem skopiować ciąg jest „przyciąć” bagaż, to przyciąć stanowiącego podstawę char tablicę do tylko to, co jest konieczne.

Podstawowa tablica znaków może być zbyt duża, ponieważ podczas tworzenia łańcucha przez wywołanie substring tablica znaków może być współużytkowana między nową instancją łańcucha a instancją źródłową; przesunięcie wskazuje na pierwszy znak, a długość jest uwzględniona.

Wyrażenie używam, „przyciąć bagaż”, pochodzi z kodem źródłowym String konstruktora kopiującego:

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; 

To jest coś, wielu deweloperów zapomnieć i to ważne, ponieważ mały ciąg może zapobiec garbowanie większej tablicy char. Zobacz to pokrewne pytanie, na które już wskazałem: Java not garbage collecting memory. Wielu programistów uważa, że ​​decyzja projektantów Javy, aby użyć tej starej sztuczki optymalizacyjnej, która była znana koderom C, w rzeczywistości przyniosła więcej szkód niż korzyści. Wielu z nas wie o tym, ponieważ byliśmy przez niego pogryzieni i musieliśmy zajrzeć do kodu źródłowego Sun, aby zrozumieć, co się stało ...

Jak zauważa Marko (patrz komentarze poniżej), w OpenJDK, począwszy od wersji Java 7 Update 6 , substring nie udostępnia już tablicy znaków, a konstruktor String(String) jest w związku z tym bezużyteczny. Ale wciąż jest szybki (jeszcze szybciej), a ponieważ ta zmiana nie została rozpowszechniona na wszystkich maszynach wirtualnych (i prawdopodobnie nie wszystkich klientach), poleciłbym zachować tę najlepszą praktykę, aby użyć new String(substring), gdy stare zachowanie uzasadniało to .

+5

... i nie ma go już od OpenJDK 7, aktualizacja 6. Nie ma już strukturalnego współdzielenia poprzez 'podłańcuch',' przycinanie' itd. –

+0

@Marko Czy możesz wskazać źródło aktualizacji, o której wspomniałeś? Nie wiedziałem o tej ważnej zmianie. –

+3

[Odniesienie tutaj] (http://hg.openjdk.java.net/jdk7u/jdk7u6/jdk/file/8c2c5d63a17e/src/share/classes/java/lang/String.java) Już mam zakładkę, to jest od kiedy nauczyłem się od Jona Skeeta o tym! –

Powiązane problemy