有两种方法可以创建String对象。
String str = new String("Java");
String str2 = "Java";
我知道在第一种情况下肯定会调用构造函数。但不知道第二个。 是否会调用构造函数?
String substr = new String(str.substring(2,str.length)); // str is new object
String substr2 = new String(str2.substring(2,str2.length)); //str2 is not with new keyword
希望确保substr
和substr2
在堆内存中具有相同的操作和相同的行为。
我知道String.substring()
根本不会创建新对象,而是使用具有不同偏移量的先前char []对象。
那么substr
和substr2
会发生什么?我们可以将这些东西与构造函数联系起来,因为在构造函数中生成了偏移量。
答案 0 :(得分:3)
来自JLS §3.10.5. String Literals:
字符串文字是对类
String
的实例的引用(§4.3.1,§4.3.3)。此外,字符串文字始终引用类
String
的同一实例。这是因为字符串文字 - 或者更常见的是作为常量表达式(第15.28节)的值的字符串 - 被“实现”以便使用方法String.intern
共享唯一实例。
因此,"Java"
指的是String
个对象。此外,由相同字符组成的任何字符串文字都将引用相同的String
对象。但是,如何以及何时构造此对象是未指定的。
希望确保
substr
和substr2
在堆内存中具有相同的操作和相同的行为。
是的,它们完全是同一种操作。
我知道
String.substring()
根本不会创建新对象,而是使用具有不同偏移量的先前char []对象。
这是未指定的。您所描述的是旧版本的Oracle JDK的工作原理。当前版本don't do that anymore:substring()
现在复制字符。此更改是在Java 7u6中进行的。
答案 1 :(得分:2)
构造函数。
如果是String str2 = "World";
,jvm将首先在字符串池中搜索字符串"world"
。只有在池中不存在该文字时才会调用构造函数,否则它将返回现有对象。
答案 2 :(得分:0)
应始终调用构造函数。 为了自己找出调试这个应用程序:
public static void main(String[] args) {
String str = new String("Java"); // <-- breakpoint here
String str2 = "World";
String str3 = "Java"; // (1)
String str4 = new String("Java"); // (2)
System.out.println(str + " " + str2 + " " + str3 + " " + str4);
}
在第一行(String str = new...
)和“Step into”设置断点以进入String()
构造函数。然后“走出”构造函数,“跳过”到下一行,然后再“步入”。你应该再次进入String()
构造函数。
1:至于str3
,它应该来自池,即if (str3 == str)
将是true
。
2:但str4
将是一个新实例,即if (str4 == str || str4 == str3)
将是false
。请参阅String API。
让我们知道你发现了什么: - )