另一个让我困惑的考试题目:
public String makinStrings() {
String s = “Fred”;
s = s + “47”;
s = s.substring(2, 5);
s = s.toUpperCase();
return s.toString();
}
问题是: "调用此方法时将创建多少个String对象?"
正确答案应该是3但我更重要的是:
弗雷德
47个
Fred47
ED4
ED4
3真的是正确答案吗?如果是这样 - 为什么?
答案 0 :(得分:1)
在实例化类时实例化字符串常量。正因为如此,字符串" Fred"和" 47"在调用方法之前实例化,而不是在方法调用期间实例化。
本文解释了它:The String Constant Pool
但我会稍微改进一下:Java虚拟机规范指定常量" Fred"和" 47"作为字符串常量池中的条目放置。 (java SE specs, loading and linking)。
加载类时会发生 。
要关注的另一点:问题是实例化了多少个对象。
所以,
String s =" Fred" :没有实例化一个新的String对象,只使用内化的" Fred"恒定。
s = s +" 47" :' +'运算符意味着连接操作;该连接的结果是一个新的String对象。因此,1 String实例化。 " 47"载满了班级......
s = s.substring(2,5):方法定义指定必须返回一个新的字符串对象(String.substring javadoc),因此,2个字符串被实例化。
即使实现(例如the openJDK java.lang.String implementation)可能使用某种构造函数来仅引用具有String内部值的字符数组的一部分,结果是一个新的String,即使是一种"懒惰的"之一。
s = s.toUpperCase():同样在这里,toUpperCase方法必须返回一个新的String。所以,3 Strings实例化了。
最后, s.toString()将对象的表示形式返回为String。由于String 已经是一个String,s.toString()只返回完全相同的String对象......
答案 1 :(得分:0)
3个对象:
弗雷德
Fred47
ED4
s = s + “47”;
47将不会在字符串池
上创建s = s.substring(2, 5);
不应创建单独的字符串,而是遵循flyweight模式并在内部指向相同的字符串。