java中string相等问题("=="与".equal"的具体区别。求详细解释)

public class Test{
public static void main(String[] args){
String s1="accp";
String s2="accp";
String s3=new String(s1);
if(s1==s2){
System.out.print("true,");
}else{
System.out.print("false,");
}
if(s1==s3){
System.out.println("true");
}else{
System.out.println("false");
}
}
}

解释结果为啥为true,false
最新回答
丸子头

2024-11-07 04:13:10

这要和String的JVM内部工作原理相结合!

比如:String s1="accp"

Java内部将此语句转化为以下几个步骤:

  (1)先定义一个名为s1的对String类的对象引用变量放到栈中:String s1;

  (2)在常量池(字符串常量池)中查找有没有存放值为"accp"的地址,如果没有,则开辟一块存放字面值为"accp",并将这一块内存的指向地址放到栈中s1的变量中。如果已经有了值为"accp"的地址,则直接返回这个地址给栈中s1变量。所以如果常量池中已经有的值,直接返回地址就好。

  String s1 = "accp"; 其字符串值是保存了一个指向常量池中值的引用!

所以s1 和s2的引用地址是相同的,所s1==s2为true

------------------------------------------------------------------------------

而Strings3=newString(s1);

 (1)先定义一个名为s3的对String类的对象引用变量放到栈中:String s3;

(2)在堆中创建一个String类型的对象,这个对象的值,也就是s1的字面值为“accp”。会按照上面的第2的操作到常量池中获取,并返回一个常量池的引用给堆中的这个对象。

(3) 将堆中创建对象的地址返回给栈中变量s3。

所以 Strings3=newString(s1); 是一个指向堆中对象的引用地址。那么 s1 == s3 为false

下面给一个图更好理解吧:

对象引用大概图示

==是比较对象的引用地址,如果要比较对象的值的话用equal吧!

----------扩展-------------------------------------------------------------------

String有一个方法intern(),返回的是这个String对象的常量池引用对象。

如果用 

String s4 = s3.intern();
String s5= new String(s1).intern();

则 s1 == s4 和 s1 == s5 都为true

--------备注------------------------------------------------------------------------

这个问题以前的答案由于本人的经验和能力的不足,导致回答有很多错误的地方,在此表示非常抱歉。

仙蒂瑞拉

2024-11-07 08:32:09

Java编译器认为String对象是不变的,所以所有这样直接写出来"accp"的常量,都编译为同一个实例(不变才能这么干,如果是能变的对象这么编译的话,结果改了s1就同时改了s2,就不对了),这就是为什么s1==s2,但是s3是new出来的实例,一定是另一个实例,当然不会s1==s3。
著墨染雨君画夕

2024-11-07 05:21:57

同一和相同的区别,==比较的是不是同一对象,equals比较的是不是相同的。