Java中有多少字符串对象?
我的朋友给我发了一个关于字符串对象的Java认证模拟考试中看到的问题:Java中有多少字符串对象?,java,string,Java,String,我的朋友给我发了一个关于字符串对象的Java认证模拟考试中看到的问题: String makeStrings(){ String s = "HI"; s = s + "5"; s = s.substring(0,1); s = s.toLowerCase(); return s.toString(); } 调用此方法时将创建多少个字符串对象? 考试的正确答案是3。但我想是五点 “嗨” “5” “HI5” “H” “h” 我错了吗 String makeS
String makeStrings(){
String s = "HI";
s = s + "5";
s = s.substring(0,1);
s = s.toLowerCase();
return s.toString();
}
调用此方法时将创建多少个字符串对象?
考试的正确答案是3。但我想是五点
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();
StringBuilder的toString()
是:
public String toString() {
return new String(value, 0, count); //so a new String is created
}
子字符串
创建一个新的字符串对象,除非整个字符串
被索引:
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);
}
toLowerCase()
是一个相当长的方法,但只要说字符串不是所有小写,它将返回一个新字符串
假设提供的答案是3
,正如Jon Skeet所建议的,我们可以假设这两个字符串文本都已经在字符串池中。有关何时向池中添加字符串的详细信息,请参阅。s=s+“5”代码>
翻译为:
String s = new StringBuilder(s).append("5").toString();
现在,创建了一个对象
创建一个新字符串
创建一个新对象
不创建字符串,它返回一个已经创建的字符串。其他一些答案确实有意义,但是字符串文字呢
String s = "HI";
对于字符串文本,当一个.java文件被编译成一个.class文件时,任何字符串文本都会以一种特殊的方式被记录,就像所有常量一样。加载类时(请注意,加载发生在初始化之前),JVM将遍历该类的代码并查找字符串文本
当它找到一个时,它会检查是否已经存在一个等价的字符串
从堆中引用。如果不是,它将在
堆并将对该对象的引用存储在常量表中
一旦对该字符串对象进行了引用,整个程序中对该字符串文本的任何引用都将被替换为对从字符串文本池引用的对象的引用
因此,应该有四个Java对象,尽管当一次又一次地调用同一个方法时,只有三个对象,因为在应用程序中,字符串文本池包含文本“HI”
此外,有关在执行上述方法块时为什么创建新对象的更多信息,我们还可以检查不同字符串的不同哈希代码(String
不可变)
您将获得以下输出:
2305
71508
72
104
104
在上面的例子中,我们不应该在字符串文本对象中计数吗?我怀疑区别在于“HI”和“5”已经在字符串池中,所以它们不是在每次方法调用时创建的。@GrijeshChauhan我在上面做了一个比较。我认为我们应该投票关闭另一个帖子,而不是关闭这个帖子。也许我有偏见,但我认为这些答案更好…@SteveP。我投票决定用复制选项关闭它…这个应该重新打开,另一个应该标记为复制。这个问题的答案更具解释性…@EJP我不认为这是那个问题的重复。尽管如此,问题之间还是应该有一些冗余。有稍微不同的问题并保持它们都是开放的并不一定是坏事……子字符串创建一个新的字符串对象,而toString不Substring
将在这里创建一个对象。只有当索引位于原始字符串的边界时,它才会返回相同的字符串-[0,s.length()-1]
@Joni,我没有意识到它实际上是在对字符串调用toString()
。我做了必要的改变(对两者都是如此)。谢谢。根据您的解释,我看到创建了4个字符串,而不是询问者所说的3个字符串:string literal、concatenation、substring和toLowerCase。@guillegr123鉴于OP提供的答案是3
,可以推断字符串literal已经添加到字符串池中。“s.toString();”返回相同的字符串?你确定吗?@loki是的toString(){returnthis}
根据OP问题中给出的答案,我们可以假设它们已经在字符串池中。尽管如此,回答还是很好(+1)。最初的问题是“调用此方法时将创建多少个字符串对象?”,推断该类已经加载,并且该方法正在从另一段代码中调用。根据您的解释,字符串文字是在加载类时创建的,而不是在调用此方法时创建的,因此不会计入所讨论的总数。
s = s.toLowerCase();
return s.toString();
String s = "HI";
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