注意:我不是要比较角色是否等于。因为我知道如何使用String.equals()方法。这个问题是关于字符串引用
当我开始学习类字符串及其属性作为不变性等时,我正在学习OCA考试。根据我读到或可能理解的字符串池是一个字符串创建Java将此对象存储在他们称为字符串池的内容中,如果创建的新字符串具有相同的值,则它将引用字符串池上的字符串除了我们使用 new 关键字的情况,因为这会创建一个新的引用,即使两个字符串都包含相同的值。
例如:
String a = "foo";
String b = "foo";
String c = new String("foo");
boolean ab = (a == b); // This return true
boolean ac = (a == c); // This return false
要清楚这段代码是在第一行代码中创建String a = "foo"
并将其存储在字符串池上,并在第二行代码上将创建String b
并引用"foo"
,因为这已存在于字符串池中。但是第3行将创建此字符串的新引用,无论它是否已存在。这是一个关于发生了什么的图形示例:
问题出现在以下代码行中。当通过连接创建字符串时,java会使某些东西变得不同或简单= =比较器有另一种行为吗?
示例A:
String a = "hello" + " world!";
String b = "hello world!";
boolean compare = (a == b); // This return true
例B:
a = "hello";
b = "hel" + "lo";
compare = (a == b); // This return true
示例C:
a = "Bye";
a += " bye!";
b = "Bye bye!";
compare = (a == b); // This return false
观看正在运行的代码:(http://ideone.com/fdk6KL)
发生了什么事?
修改
示例B中的修复错误:b = 'hel' + 'lo'
添加有关问题的说明。这不是一个比较问题,因为我知道String.equals()
使用public void onJoin(String channel, String sender, String login, String hostname)
{
//check to see if another user joines
}
问题是在字符串池上的引用
答案 0 :(得分:6)
"当串联创建字符串时,java会创建一些东西 不同或简单==比较器有另一种行为吗?"
不,它不会改变它的行为,会发生什么:
当连接两个字符串文字"a" + "b"
时,jvm连接两个值,然后检查字符串池,然后它实现池中已存在的值,因此它只是简单地将此引用分配给String。现在更详细:
查看下面这个简单程序的编译字节码:
public class Test {
public static void main(String... args) {
String a = "hello world!";
String b = "hello" + " world!";
boolean compare = (a == b);
}
}
首先,JVM加载字符串" hello world!然后将其推送到字符串池(在本例中),然后将其加载到堆栈(ldc =加载常量) [参见图像中的第1点]
然后它将池中创建的引用分配给局部变量(astore_1) [参见图像中的第2点]
请注意,在字符串池中为此文字创建的引用为#2 [参见图像中的第3点]
下一个操作大致相同:在连接字符串时,将其推送到运行时常量池(在本例中为字符串池),但随后它会实现具有相同内容的文字已存在,因此它使用此引用(# 2)并分配一个局部变量(astore_2)。
因此当你这样做时(a == b)是 true 因为它们都引用了字符串池#2,即#34; hello world!"。
您的示例C有点不同,因为您使用的是+ =运算符,当编译为字节码时,它使用StringBuilder来连接字符串,因此这会创建一个StringBuilder对象的新实例,从而指向不同的参考。 (字符串池vs对象)