我的朋友给我发了一个他在一次模拟考试中看到的有关字符串对象的Java认证的问题:
String makeStrings(){
String s = "HI";
s = s + "5";
s = s.substring(0,1);
s = s.toLowerCase();
return s.toString();
}
调用此方法时将创建多少个字符串对象? 考试给出的正确答案是3.但我认为这是五个。
我错了吗?
答案 0 :(得分: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
}
关于连接,在创建新字符串时,JVM
使用StringBuilder
,即:
s = new StringBuilder(s).append("5").toString();
对于toString()
, StringBuilder
是:
public String toString() {
return new String(value, 0, count); //so a new String is created
}
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);
}
toString()
不创建新字符串:
public String toString()
{
return this;
}
toLowerCase()
这是一个非常长的方法,但是如果String
已经全部小写,那么将返回new String
。
鉴于所提供的答案是3
,正如Jon Skeet建议的那样,我们可以假设两个字符串文字已经在字符串池中。有关何时将字符串添加到池中的更多信息,请参阅Questions about Java's String pool。
答案 1 :(得分:13)
s = s + "5";
翻译为:
String s = new StringBuilder(s).append("5").toString();
现在,创建了一个Object。
s = s.substring(0,1);
创建一个新的String。
s = s.toLowerCase();
创建一个新对象。
return s.toString();
不创建String,它返回已经创建的String。
答案 2 :(得分:9)
其他一些答案确实有意义,但字符串文字怎么样?
String s = "HI";
对于字符串文字,当.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();
}
您将获得以下输出:
2305
71508
72
104
104
我们不应该在上面的例子中计算String文字对象吗?