Java中.equals()与==的区别及二者适用场景咨询
字符串比较:== vs .equals()的核心差异与场景分析
一、为什么调用.toString()后只能用.equals()?
当你调用toString()方法时,绝大多数场景下会生成全新的String对象(除非类重写的toString()刻意返回常量池中的字符串,这属于特例)。举个例子:
Integer num = 123; String s1 = num.toString(); String s2 = num.toString();
这里的s1和s2是堆内存中两个完全独立的对象,它们的内存引用地址完全不同。而==在比较对象时,本质是对比两个变量指向的内存地址是否一致,而非字符串内容,所以s1 == s2会返回false。
而String类重写过的.equals()方法,是专门用来对比字符串的字符序列是否完全一致,不管两个对象是不是同一个实例,只要内容匹配就返回true,因此这种场景下必须用.equals()。
二、为什么有些字符串能用==比较?
这要归功于Java的字符串常量池机制:
- 直接用双引号声明的字符串常量,会被存入常量池。比如:
a和b指向的是常量池里的同一个对象,所以String a = "hello"; String b = "hello";a == b会返回true。 - 调用
String.intern()方法的字符串,会将引用指向常量池中对应的字符串(如果常量池已存在该字符串)。比如:
此时String c = new String("hello").intern(); String d = "hello";c == d也会返回true。 - 编译期可确定的字符串拼接结果,会被编译器优化后存入常量池。比如:
编译器会把String e = "hel" + "lo"; String f = "hello";"hel"+"lo"直接优化为"hello",所以e和f指向同一个常量池对象,e == f为true。
但要注意:如果是运行时才确定的拼接(比如包含变量),会生成新的对象,此时不能用==比较:
String g = "hel"; String h = g + "lo"; String i = "hello";
这里h是运行时拼接生成的新对象,不在常量池中,所以h == i会返回false。
三、==与.equals()的适用场景
==的适用场景
- 比较基本数据类型:比如int、char、boolean等,此时==直接对比值本身。
- 比较对象引用:判断两个变量是否指向内存中的同一个对象(比如判断对象是否为null,或者确认两个变量指向同一个实例)。
.equals()的适用场景
- 比较对象的内容是否相等:对于所有重写了equals()方法的类(比如String、Integer、Date等),用它来判断内容是否匹配。
- 注意:如果自定义类没有重写equals(),会默认继承Object类的equals(),此时它和==效果一致,都是对比引用地址,所以自定义类需按需重写equals()来实现内容比较。
内容的提问来源于stack exchange,提问作者Gargouri Nourallah
相关产品推荐
相关产品推荐

