Java 为什么新字符串()和#x2B;new String()在JDK8下返回不同的结果
以下代码在JDK8 1.8.0_171下具有不同的结果Java 为什么新字符串()和#x2B;new String()在JDK8下返回不同的结果,java,string,Java,String,以下代码在JDK8 1.8.0_171下具有不同的结果 @Test public void test2() { String s1 = new String("a") + new String("a"); s1.intern(); String s2 = "aa"; System.out.println(s1 == s2); //true } @Test public void test3() {
@Test
public void test2() {
String s1 = new String("a") + new String("a");
s1.intern();
String s2 = "aa";
System.out.println(s1 == s2); //true
}
@Test
public void test3() {
String s1 = new String("1") + new String("1");
s1.intern();
String s2 = "11";
System.out.println(s1 == s2); //false
}
唯一的区别是值:“a”而不是“1”,我得到的结果是不同的。这是为什么?s1.intern()
仅将s1
引用的字符串添加到字符串
池中,前提是该池中尚未包含与其相等的字符串
诸如“aa”和“11”之类的字符串文本始终处于内部,因此它们将始终是=
由s1.intern()返回的实例
因此,s1==s2
是否返回true
取决于字符串所包含的池在调用s1.intern()
之前是否等于s1
- 如果是这样,
s1.intern()
即==s2
不是==s1
,因此System.out.println(s1==s2)
将打印false
- 如果没有,则
s1.intern()==s1==s2
,因此System.out.println(s1==s2)
将打印true
这可以在Java版本之间更改,因为不同版本的JDK类可能包含不同的字符串文本集,这些文本在执行代码之前会自动插入。因为=
操作符检查两个变量是否引用完全相同的对象。比如说
String s1 = new String("foo");
String s2 = s1;
System.out.println(s1 == s2); //true
如果您有两个单独的实例,并且希望根据它们的值比较字符串,那么应该使用String::equals
String s1 = new String("foo");
String s2 = new String("foo");
System.out.println(s1.equals(s2)); //true
请退房
当涉及到String:intern时,您必须在两个实例上调用它,以便比较它们,而不仅仅是其中一个<代码>字符串foo=“foo”
仍然隐式创建字符串的新实例。Java中没有原语string
String s1 = new String("foo");
String s2 = "foo";
System.out.println(s1.intern() == s2.intern());
这是为了给埃兰的伟大答案添加一个例证。以下假设“aa”
在执行代码之前未被实习(隐式或非隐式):
s1
和s3
都有相同的文本(“aa”
),因此实际文本中的差异不会造成差异。对.intern()
的第二次调用没有导致s3
被放入池中(因为池中已经包含“aa”
,这是s1.intern()
的结果),解释了=
在s3
和s2
之间返回false的原因
简而言之,这意味着在执行test3()
方法之前,“11”
已被实习
对于附加测试,移动String s2=“aa”代码>到代码的开头(两个比较都返回false
,原因相同-尽管这可能取决于版本或实现)我根本不依赖=
进行字符串比较,也就是说,它们是否已被占用并不重要。因此,从实际的角度来看,这个问题可能是没有意义的。为了验证这一点:只需添加一个打印(或处理)字符串常量的test0
“aa”
,就会使test2
打印错误(只要test0
在test2
之前执行)。聪明的答案。花了几秒钟的时间来了解您所谈论的内容。JVM之间另一个明显的变化是,文本是在类加载时、类初始化时还是。。。第一次执行某个方法时,总是懒洋洋的。@ernest_k我还是不明白:(这很令人困惑,因为在test2
中,输出会根据是否调用intern
而变化。似乎intern
会将s1
重新分配给其他对象!如果是s1=s1.intern();
,这两个测试都是正确的,但由于返回值被忽略(intern
仅将字符串添加到字符串池中,但由于aa
和11
是文本,它们已经存在,因此intern
实际上什么都不做),为什么test2
仍然打印为true?@Sweeper:不,intern
不能也不会更改s1
是什么。但是当使用该方法首次插入字符串值时,调用intern
的实际实例将成为该实习生池的成员。因此,与其intern
更改s1
的内容>也就是说,它改变了从实习生池初始化时,s2
将变成什么:由s1
实习的值,或者(如果您不调用intern
)它变成了一个新的字符串实例,其值与放入intern池的值相同。这是基本情况信息。但它没有解释OP提供的两个测试为何会产生不同的输出,也没有解释调用s1.intern()的原因
如果不将结果重新传回s1
将更改测试的输出。
String s1 = new String("a") + new String("a");
s1.intern();
String s2 = "aa";
System.out.println(s1 == s2); //true
String s3 = new String("a") + new String("a"); //same text
s3.intern();
System.out.println(s3 == s2); //false