Java中有多少个字符串对象?

Mau*_*o M 38 java string

我的朋友给我发了一个问题,他在一次模拟考试中看到了关于字符串对象的Java认证:

String makeStrings(){
    String s = "HI";
    s = s + "5";
    s = s.substring(0,1);
    s = s.toLowerCase();
    return s.toString();
}
Run Code Online (Sandbox Code Playgroud)

调用此方法时将创建多少个字符串对象?考试给出的正确答案是3.但我认为这是五.

  1. "HI"
  2. "5"
  3. "HI5"
  4. "H"
  5. "H"

我错了吗?

Ste*_* P. 46

String makeStrings() {
    String s = "HI";           //String literal
    s = s + "5";               //concatenation creates new String object (1)
    s = s.substring(0,1);      //creates new String object (2)
    s = s.toLowerCase();       //creates new String object (3)
    return s.toString();       //returns already defined String
}
Run Code Online (Sandbox Code Playgroud)

关于连接,在创建新String时,JVM使用StringBuilder,即:

s = new StringBuilder(s).append("5").toString(); 
Run Code Online (Sandbox Code Playgroud)

toString()对于a StringBuilder是:

public String toString() {
    return new String(value, 0, count); //so a new String is created
}
Run Code Online (Sandbox Code Playgroud)

substring创建一个新的String对象,除非整个String索引:

public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > count) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    if (beginIndex > endIndex) {
        throw new StringIndexOutOfBoundsException(endIndex - beginIndex)
    }

    return ((beginIndex == 0) && (endIndex == count)) ? this :
           new String(offset + beginIndex, endIndex - beginIndex, value);
}
Run Code Online (Sandbox Code Playgroud)

toString()确实不是创建一个新的字符串:

public String toString()
{
   return this;
}
Run Code Online (Sandbox Code Playgroud)

toLowerCase()是一个相当长的方法,但我只想说,如果String不是已经全部小写,它返回一个new String.

鉴于所提供的答案是3,正如Jon Skeet所建议的那样,我们可以假设两个字符串文字都已经存在于字符串池中.有关何时将字符串添加到池中的更多信息,请参阅有关Java字符串池的问题.


Mar*_*oun 13

s = s + "5";

被翻译成:

String s = new StringBuilder(s).append("5").toString();
Run Code Online (Sandbox Code Playgroud)

现在,创建了一个Object.


s = s.substring(0,1); 
Run Code Online (Sandbox Code Playgroud)

创建一个新的String.


s = s.toLowerCase();
Run Code Online (Sandbox Code Playgroud)

创建一个新对象.


return s.toString(); 
Run Code Online (Sandbox Code Playgroud)

不创建String,它返回已经创建的String.

  • @loki yes ..`toString(){return this}` (7认同)

小智 9

其他一些答案确实有意义,但字符串文字怎么样?

String s = "HI";
Run Code Online (Sandbox Code Playgroud)

对于字符串文字,当.java文件被编译成.class文件时,任何字符串文字都以特殊方式记录,就像所有常量一样.加载类时(注意在初始化之前加载),JVM会遍历类的代码并查找字符串文字.

当找到一个时,它会检查是否已从堆中引用了等效的String.如果没有,它会在堆上创建一个String实例,并在常量表中存储对该对象的引用

一旦引用了该字符串对象,整个程序中对该字符串文字的任何引用都将被替换为对字符串文字池引用的对象的引用.

因此应该有四个Java对象,尽管当一次又一次地调用相同的方法时,在应用程序中只有三个对象,字符串文字池包含文字"HI".

此外,有关为什么在上述方法块被激活时创建新对象的原因的更多信息,我们还可以检查不同字符串的不同哈希码(String不可变).

  public static void main(String[] args)
  {
      NumberOfString str = new NumberOfString();
      String s = str.makeStrings();
      System.out.println(s.hashCode());
  }

  public String makeStrings()
  {
      String s = "HI";
      System.out.println(s.hashCode());
      s = s + "5";
      System.out.println(s.hashCode());
      s = s.substring(0, 1);
      System.out.println(s.hashCode());
      s = s.toLowerCase();
      System.out.println(s.hashCode());
      return s.toString();
  }
Run Code Online (Sandbox Code Playgroud)

您将获得以下输出:

2305
71508
72
104
104
Run Code Online (Sandbox Code Playgroud)

我们不应该在上面的例子中计算String文字对象吗?