首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Java中连接字符串时使用"==“

在Java中连接字符串时使用"==“
EN

Stack Overflow用户
提问于 2015-12-29 18:58:18
回答 7查看 2.3K关注 0票数 54
代码语言:javascript
复制
String a = "devender";
String b = "devender";
String c = "dev";
String d = "dev" + "ender";
String e = c + "ender";

System.out.println(a == b);     //case 1: o/p true

System.out.println(a == d);     //case 2: o/p true

System.out.println(a == e);     //case 3: o/p false

a & b两者都指向字符串常量池中的相同字符串文字。所以在第一种情况下使用true

代码语言:javascript
复制
String d = "dev" + "ender";

应该在内部使用类似如下的内容:

代码语言:javascript
复制
String d = new StringBuilder().append("dev").append("ender").toString();

& d如何指向相同的引用& a & e

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2015-12-29 19:04:22

有四件事正在发生:

  1. (您很清楚这一点,但是对于潜伏者) ==测试以查看变量是否指向same object,而不是等价的字符串。因此,即使x"foo"y也为"foo"x == y也可能为真或假,这取决于xy引用的是同一个String对象还是不同的对象。这就是为什么我们使用equals而不是==来比较字符串的等价性。以下所有内容只是为了解释为什么==有时是真的,并不建议使用==来比较字符串。相同类中的:-)
  2. Equivalent字符串常量(根据JLS中的各种规则,编译器知道它们是常量)由编译器引用相同的字符串(编译器还在类的"constant pool"中列出它们)。这就是a == b为true的原因。
  3. 当装入类时,它的每个字符串常量都会自动为-检查JVM的字符串池中是否有等价的字符串,如果找到,则使用该String对象(如果没有找到,则将新常量的新String对象添加到池中)。因此,即使x是在Foo类中初始化的字符串常量,y是在Bar类中初始化的字符串常量,它们也会相互==

上面的第2点和第3点在JLS§3.10.5中有所涉及。(关于类常量池的部分是实现细节,因此前面提供了到JVM规范的链接;JLS只是说如果处理常量值,interning.)

  • The编译器就会进行字符串连接,所以

String d= "dev“+ "ender";

被编译为

String d= "devender";

"devender"是一个字符串常量,编译器和JVM将上面的第2点和第3点应用于它。例如,没有使用StringBuilder,则串联发生在编译时,而不是运行时。这在JLS§15.28 - 中有介绍。因此,a == d为true的原因与a == b为true的原因相同:它们引用相同的常量字符串,因此编译器确保它们引用类的常量池中的相同字符串。

当任何一个操作数不是常量时,编译器不能这样做,所以它不能这样做:

字符串e=c+ "ender";

...even虽然代码分析可以很容易地显示c的值肯定是"dev",因此e肯定是"devender"。该规范只让编译器使用常量值进行连接,特别是。因此,由于编译器无法做到这一点,它将输出您引用的StringBuilder代码,并在运行时创建一个新的String对象。该字符串不会自动内嵌,因此e最终引用了与a不同的String对象,因此a == e为false。

请注意,如果您将c声明为final,则as Vinod said

最后一个字符串c= "dev";

然后它将是一个 (是的,它们确实是这样叫的),因此将应用§15.28,编译器将

字符串e=c+ "ender";

转到

字符串e= "devender";

a == e也是真的。

只是重申一下:这并不意味着我们应该使用==来比较字符串的等价性。:-)这就是equals的作用。

票数 83
EN

Stack Overflow用户

发布于 2015-12-29 19:05:10

编译器在幕后做了很多优化。

字符串d= "dev“+ "ender";

在这里,当编译程序时,编译器会用"devender"替换"dev" + "ender"。如果您要添加2个文字(这适用于原语和字符串),编译器将执行此优化。

Java代码:

代码语言:javascript
复制
String d = "dev" + "ender";

字节码:

代码语言:javascript
复制
  0: ldc           #16                 // String devender

到了一个特殊的情况:

最终字符串c= "dev";//标记为最终字符串e=c+ "ender";

c设为final将使字符串成为编译时间常量。编译器将意识到c的值不能改变,因此在编译时将所有出现的c替换为"dev“值,因此e将在编译时本身解析。

票数 17
EN

Stack Overflow用户

发布于 2015-12-29 19:04:05

正如您在内部所说的,最后一个连接是对类似于

代码语言:javascript
复制
String e = new StringBuilder().append(c).append("ender").toString();

StringBuilder toString()实现创建了一个新的字符串。下面是实现。

代码语言:javascript
复制
public String toString() {
     // Create a copy, don't share the array
     return new String(value, 0, count);
}

仅当两个字符串是相同的true时,使用==而不是.equals() 比较字符串才会返回。在本例中,因为第二个字符串是作为String.类型的新对象创建的,所以它们不同

其他连接是由编译器直接执行的,因此不会创建新的字符串。

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

https://stackoverflow.com/questions/34509566

复制
相关文章

相似问题

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