12

javax.sql パッケージの多くのクラスはnew String(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("");
}

または

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

などなど:

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

これの目的は何ですか?ヒープ上に不要な文字列インスタンスを作成していませんか?

4

2 に答える 2

9

それらは潜在的に「大きな文字列の小さな部分」の問題から保護しています:

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

yによって参照される文字列が必要なままであると仮定しますが、そうでxはありません。y元の を参照しているためchar[]、その小さな文字列が多くのメモリを担当することになります。

代わりに新しい文字列を作成し、データをコピーする場合:

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

... 次に、元の文字列に関連付けられた基になる大きな char 配列を、文字列と同時にガベージ コレクションすることができます。

大きなテキスト ファイル (辞書の単語など) から多くの小さな行を読み取るときに、これが大きな違いを生むのを見てきました。IIRCは 80 文字のバッファを作成するため、各文字列は5 文字しかない場合でも、BufferedReader.readLine少なくとも 80 文字のピンを返します。char[]それはすべて合計されます...(コメントによると、明らかにこれはJava 1.5で変更されましreadLineたが、substringそれでも同じように機能します。)

編集:もちろん、それは理由についての推測に過ぎず、間違いなくそのnew String("")部分を説明していません...

于 2012-08-08T18:01:20.350 に答える
6

コードが JDK6 から JDK7 に変更され、 のすべてのインスタンスnew String(str)が削除されたようです。したがって、Jon Skeet の提案は非常に興味深いものですが、おそらく彼らが見つけて修正した不完全なコードでした。

于 2012-08-08T18:06:21.380 に答える