2012-08-08 13 views
12

Wiele klas w pakiecie javax.sql używa konstruktora new String(str). Na przykład:Dlaczego klasy w pakiecie javax.sql używają nowego ciągu (str)?

public void setCatalogName(int columnIndex, String catalogName) throws SQLException { 
    checkColRange(columnIndex); 
    if (catalogName != null) 
     colInfo[columnIndex].catName = new String(catalogName); 
    else 
     colInfo[columnIndex].catName = new String(""); 
} 

Albo

public void setUsername(String name) { 
    if(name == null) 
    { 
     username = null; 
    } else { 
     username = new String(name); 
    } 
} 

i wiele więcej:

javax.sql.rowset.serial.SerialStruct.SerialStruct (Sqldata, mapa>) javax.sql. rowset.serial.SerialStruct.SerialStruct (Struct, Map>) javax.sql.rowset.RowSetMetaDataImpl.setCatalogName (int, String) javax.sql.rowset.RowSetMetaDataImpl.setColumnLabel (int, String) javax.sql.rowset.RowSetMetaDataImpl.setColumnName (int, string) javax.sql.rowset.RowSetMetaDataImpl.setColumnTypeName (int, string) javax.sql.rowset.BaseRowSet.setCommand (String) javax.sql.rowset. BaseRowSet.setDataSourceName (String) java.text.DateFormatSymbols.setLocalPatternChars (String) javax.sql.rowset.BaseRowSet.setNull (int, int, string)

Jaki jest cel tego? Czy nie tworzy niepotrzebnych instancji napisów na stercie?

+1

Według którego wdrożenia JDK? OpenJDK? – oldrinb

+1

JDK6, Oracle .... Właśnie sprawdziłem JDK7, i jest tam naprawiony – Bozho

+0

Rzeczywiście, nie widzę żadnego z nich w [OpenJDK 7] (http://grepcode.com/file_/repository.grepcode.com /java/root/jdk/openjdk/7-b147/javax/sql/rowset/RowSetMetaDataImpl.java). – oldrinb

Odpowiedz

6

Wygląda na to, że kod został zmieniony z JDK6 na JDK7, a wszystkie wystąpienia new String(str) zostały usunięte. Tak więc, chociaż sugestia Jona Skeeta jest dość interesująca, prawdopodobnie był to lame kawałek, który znaleźli i naprawili.

9

Oni potencjalnie ochronę przeciw „małej części dużego napisu” problem:

String x = getHugeStringFromSomewhere(); 
String y = x.substring(0, 5); 
foo(y); 

Załóżmy teraz ciąg mowa o y wymagane pozostaje, ale x nie. Ponieważ y odnosi się do oryginalnego char[], kończy się to tym, że mały ciąg odpowiada za dużo pamięci.

Jeśli utworzysz nowy łańcuch zamiast kopiowania danych:

String x = getHugeStringFromSomewhere(); 
String y = new String(x.substring(0, 5)); 
foo(y); 

... wtedy podstawowa duża tablica char związane z oryginalnego napisu mogą być zbierane śmieci w tym samym czasie, co ciąg.

Widziałem, że robi to ogromną różnicę, czytając wiele małych linii z dużego pliku tekstowego (np. Słów w słowniku). IIRC, BufferedReader.readLine tworzy bufor o długości 80 znaków, więc każdy ciąg znaków zwrócił co najmniej 80-znakowy kod char[], nawet jeśli ma tylko 5 znaków. To wszystko się sumuje ... (Jak na komentarze, najwyraźniej zmieniło się to w Javie 1.5 dla readLine - ale substring nadal działa w ten sam sposób.)

EDYCJA: Oczywiście to tylko odgadnięcie co do przyczyny, i to zdecydowanie nie wyjaśnia części new String("") ...

+0

Dzięki, podłańcuchanie działające w ten sposób należy wziąć pod uwagę. Kod, o którym mowa, został usunięty w JDK7, więc prawdopodobnie był to tylko kulawy fragment, który odkryli i naprawili :) – Bozho

+0

Chociaż może to nie być faktyczny powód, to wciąż wspaniała rzecz do zapamiętania i rozważenia na temat pamięci. +1 – Bozho

+0

'nowy ciąg (" ")' ??/Implementacja StringBuffer/String zmieniła się w 1.5 (osiem lat temu), teraz zawsze kopiuje kopię char []. readLine używa tylko StringBuffer, gdy linia przekracza bufor (domyślnie 8192 znaków). –

Powiązane problemy