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
String d = "dev" + "ender";
应该在内部使用类似如下的内容:
String d = new StringBuilder().append("dev").append("ender").toString();
& d如何指向相同的引用& a & e?
发布于 2015-12-29 19:04:22
有四件事正在发生:
==
测试以查看变量是否指向same object,而不是等价的字符串。因此,即使x
为"foo"
,y
也为"foo"
,x == y
也可能为真或假,这取决于x
和y
引用的是同一个String
对象还是不同的对象。这就是为什么我们使用equals
而不是==
来比较字符串的等价性。以下所有内容只是为了解释为什么==
有时是真的,并不建议使用==
来比较字符串。相同类中的:-)a == b
为true的原因。String
对象(如果没有找到,则将新常量的新String
对象添加到池中)。因此,即使x
是在Foo
类中初始化的字符串常量,y
是在Bar
类中初始化的字符串常量,它们也会相互==
。上面的第2点和第3点在JLS§3.10.5中有所涉及。(关于类常量池的部分是实现细节,因此前面提供了到JVM规范的链接;JLS只是说如果处理常量值,interning.)
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
的作用。
发布于 2015-12-29 19:05:10
编译器在幕后做了很多优化。
字符串d= "dev“+ "ender";
在这里,当编译程序时,编译器会用"devender"
替换"dev" + "ender"
。如果您要添加2个文字(这适用于原语和字符串),编译器将执行此优化。
Java代码:
String d = "dev" + "ender";
字节码:
0: ldc #16 // String devender
到了一个特殊的情况:
最终字符串c= "dev";//标记为最终字符串e=c+ "ender";
将c
设为final将使字符串成为编译时间常量。编译器将意识到c
的值不能改变,因此在编译时将所有出现的c
替换为"dev“值,因此e
将在编译时本身解析。
发布于 2015-12-29 19:04:05
正如您在内部所说的,最后一个连接是对类似于
String e = new StringBuilder().append(c).append("ender").toString();
StringBuilder
的toString()
实现创建了一个新的字符串。下面是实现。
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
仅当两个字符串是相同的true
时,使用==
而不是.equals()
比较字符串才会返回。在本例中,因为第二个字符串是作为String
.类型的新对象创建的,所以它们不同
其他连接是由编译器直接执行的,因此不会创建新的字符串。
https://stackoverflow.com/questions/34509566
复制相似问题