首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >方法返回的字符串+字符串与字符串+字符串

方法返回的字符串+字符串与字符串+字符串
EN

Stack Overflow用户
提问于 2016-07-04 10:00:38
回答 2查看 80关注 0票数 1

今天,在使用String的时候,我遇到了一种我以前不知道的行为。我无法理解内部发生了什么。

代码语言:javascript
复制
    public String returnVal(){
         return "5";
     }
 String s1 = "abcd5";
 String s2 = "abcd"+"5";

 String s3 = "abcd5";
 String s4 = "abcd"+returnVal();

 System.out.println(s1 == s2);
 System.out.println(s1.equals(s2));
 System.out.println(s3 == s4);
 System.out.println(s3.equals(s4));

我的期望是从所有的S.O.P.打印“真”,但是s3 == s4是假的,为什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-04 10:53:06

您无意中发现了Java编译器如何优化String的复杂问题。

假设我有这样的程序:

代码语言:javascript
复制
String a = "abc";
String b = "abc";

在这里,编译器可以将ab初始化为同一个String实例。这就需要a == ba.equals(b)

在这里,我们也得到了同样的行为:

代码语言:javascript
复制
String a = "abc";
String b = "ab" + "c";

这是因为"ab" + "c"可以在编译时计算到"abc",而"abc"又可以与a共享一个实例。

调用函数的表达式不可能使用此技术:

代码语言:javascript
复制
String a = "abc";
String b = "ab" + functionThatReturnsC();

这是因为functionThatReturnsC可能有副作用,无法在编译时解决.

您的returnVal案例很有趣。因为它是常量,所以它可以内联,在这种情况下,可以应用编译时实例共享。编译器实现者似乎决定不支持这一点。

这个问题暴露了Java的一个弱点。由于我们不能覆盖=,程序员不能实现自定义的值类型。因此,您应该始终使用equalsObjects.equals来确保行为一致。

注意,这些优化在编译器之间可能有所不同。

票数 0
EN

Stack Overflow用户

发布于 2016-07-04 10:45:12

我的期望是从所有的S.O.P.打印“真”,但是s3 == s4是假的,为什么?

编译器可以执行常量表达式内联。这意味着

代码语言:javascript
复制
String s1 = "abcd5";
String s2 = "abcd"+"5";
final String five = "5"; // final reference
String sa = "abcd" + five;

都是相同的(five除外),编译器可以将所有这些表达式简化为"abcd5"

但是,如果编译器无法优化表达式,则在运行时执行操作,并创建一个新字符串。这个新字符串不是一个常量,它位于字符串文字池中(因为它不是字节码中的文字)。

代码语言:javascript
复制
 String s4 = "abcd" + returnVal(); //  not inlined by the compiler.
 String f5 = "5";  // not a final reference.
 String sb = "abcd" + f5; // evaluated at runtime

它们每次运行时都会创建新的字符串(以及新的StringBuilderchar[])。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38181878

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档