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指的是 original char[],所以你最终会得到负责大量内存的那个小字符串。

如果您改为创建新字符串,则复制数据:

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

...那么与原始字符串关联的底层大字符数组可以与字符串同时被垃圾收集。

当从大文本文件(例如字典中的单词)中读取大量小行时,我已经看到这会产生巨大的差异。IIRC,BufferedReader.readLine创建一个 80 个字符的缓冲区,因此每个字符串返回 pin 至少一个 80-character char[],即使它只有 5 个字符长。这一切都加起来了......(根据评论,显然这在 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 回答