为什么一个 String 不指向 String 池区中的同一个对象?
Why a String do not point to the same object in the String pooled area?
我知道字符串是不可变的。在下面的示例中,将在 String 池区中创建一个 String 常量对象,并且 s1
将指向 "Hello"
。此外 s2
将创建一个具有相同值 "Hello"
的字符串常量。
但是我不明白为什么s2
不指向第一个"Hello"。据我了解,字符串 "Hello" 已经存在于字符串池区域中,如果我使用此值创建 另一个 字符串,它将指向现有对象而不是创建另一个对象。例如 s3
指向与 s1
相同的对象。
我没有为 s2
使用 new
关键字。为什么 s2
不像 s1 和 s3 指向同一个对象?
public class DemoApp {
public static void main(String args[]) {
String s1 = "Hello";
String s2 = "Hello friends".substring(0, 5);
String s3 = "Hello";
System.out.println(s2); //Hello
System.out.println(s1 == s2); //false
System.out.println(s1 == s3); //true
}
}
输出为:
Hello
false
true
仅池化字符串文字(和编译时的常量)。
substring
调用计算了一个新的 String
,它不是来自池。毕竟,substring
事先并不知道其结果是否已经合并。因此,它必须为新的 String
分配 space,以防结果不在池中。然后,如果结果的 space 已经分配,如果该结果已经被池化,那么 "check" 是浪费的。因此,您得到了您所看到的行为——substring
结果没有合并,即使它等于池中的其他结果。
如果您查看 substring 方法的实现,您会看到它使用 new 运算符创建了一个 String,因此返回的字符串不存在于字符串池中。
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
替换您的代码
String s2 = "Hello friends".substring(0, 5);
与
字符串 s2 = "Hello friends".substring(0, 5).intern();
你会看到它返回 true。
我知道字符串是不可变的。在下面的示例中,将在 String 池区中创建一个 String 常量对象,并且 s1
将指向 "Hello"
。此外 s2
将创建一个具有相同值 "Hello"
的字符串常量。
但是我不明白为什么s2
不指向第一个"Hello"。据我了解,字符串 "Hello" 已经存在于字符串池区域中,如果我使用此值创建 另一个 字符串,它将指向现有对象而不是创建另一个对象。例如 s3
指向与 s1
相同的对象。
我没有为 s2
使用 new
关键字。为什么 s2
不像 s1 和 s3 指向同一个对象?
public class DemoApp {
public static void main(String args[]) {
String s1 = "Hello";
String s2 = "Hello friends".substring(0, 5);
String s3 = "Hello";
System.out.println(s2); //Hello
System.out.println(s1 == s2); //false
System.out.println(s1 == s3); //true
}
}
输出为:
Hello
false
true
仅池化字符串文字(和编译时的常量)。
substring
调用计算了一个新的 String
,它不是来自池。毕竟,substring
事先并不知道其结果是否已经合并。因此,它必须为新的 String
分配 space,以防结果不在池中。然后,如果结果的 space 已经分配,如果该结果已经被池化,那么 "check" 是浪费的。因此,您得到了您所看到的行为——substring
结果没有合并,即使它等于池中的其他结果。
如果您查看 substring 方法的实现,您会看到它使用 new 运算符创建了一个 String,因此返回的字符串不存在于字符串池中。
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
替换您的代码
String s2 = "Hello friends".substring(0, 5);
与 字符串 s2 = "Hello friends".substring(0, 5).intern();
你会看到它返回 true。