2012-08-08 6 views
12

Molte classi nel pacchetto javax.sql utilizzano il costruttore new String(str). Per esempio:Perché le classi nel pacchetto javax.sql utilizzano la nuova stringa (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(""); 
} 

O

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

E molti di più:

javax.sql.rowset.serial.SerialStruct.SerialStruct (SQLData, mappa>) 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)

Qual è lo scopo di tutto questo? Non sta creando istanze di stringa non necessarie sull'heap?

+1

In base a quale implementazione JDK? OpenJDK? – oldrinb

+1

JDK6, Oracle .... Ho appena controllato JDK7, ed è stato risolto lì – Bozho

+0

In effetti, non vedo nulla di tutto ciò in [OpenJDK 7] (http://grepcode.com/file_/repository.grepcode.com /java/root/jdk/openjdk/7-b147/javax/sql/rowset/RowSetMetaDataImpl.java). – oldrinb

risposta

6

Sembra che il codice sia stato modificato da JDK6 a JDK7 e che tutte le istanze di new String(str) siano state rimosse. Quindi, sebbene il suggerimento di Jon Skeet sia piuttosto interessante, è stato probabilmente un pezzo di codice zoppo che hanno trovato e risolto.

9

Sono potenzialmente protezione contro la "piccola parte di un grande stringa" problema:

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

Supponiamo ora che rimane necessaria la stringa a cui si riferisce y, ma x non lo fa. Poiché char[] si riferisce allo , si finisce con quella piccola stringa che è responsabile di molta memoria.

Se si crea una nuova stringa, invece, la copia dei dati:

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

... poi sottostante grandi array di caratteri associato con la stringa originale può essere garbage collection, allo stesso tempo come la stringa.

Ho visto questo fare una grande differenza quando si leggono molte piccole righe da un file di testo di grandi dimensioni (ad esempio parole in un dizionario). IIRC, BufferedReader.readLine crea un buffer di 80 caratteri, quindi ogni stringa ha restituito almeno uno 80 caratteri, char[], anche se ha una lunghezza di soli 5 caratteri. Tutto questo si aggiunge ... (Come per i commenti, a quanto pare questo è cambiato in Java 1.5 per readLine - ma substring funziona ancora allo stesso modo.)

EDIT: Certo che è ancora solo un'ipotesi come alla ragione, ed è sicuramente non spiega la parte new String("") ...

+0

Grazie, la sottostringa che funziona in quel modo è qualcosa da considerare .. Il codice in questione viene rimosso in JDK7, quindi probabilmente era solo un pezzo di codice zoppo scoperto e risolto :) – Bozho

+0

Anche se questo potrebbe non essere il vero motivo, è ancora una grande cosa da notare e considerare sulla memoria. +1 – Bozho

+0

'new String (" ")' ??/L'implementazione di StringBuffer/String cambiata in 1.5 (otto anni fa), ora copia sempre il backing char []. readLine utilizza StringBuffer solo quando una linea attraversa un buffer (default 8192 caratteri). –

Problemi correlati