如何在JAVA中比较字符串(string)?

我们有两个字符串a和b,如何比较它们呢?用==还是.equals()?

==.equals()有什么区别

==比较的左右两侧的值。当左右两侧为基本类型的时候,直接比较值,当左右两侧为引用类型的时候,比较的是引用本身的值。字符串变量为引用类型,因此==比较的是字符串引用本身的值。
.equals()一般是java类中声明的比较方法,比较自己和另一个实例是否为同一个值。string类型已经实现了.equals()方法,会比较自身和另一个字符串是否相等。

为什么有时候==在相同字符串的时候会返回true

查看下列代码:

String val1 = "val";
String val2 = "val";
// 输出为 true
System.out.println(val2 == val1);

因为字符串在java中非常常用,出于性能和复用的考虑,代码中直接声明的字符串会直接在字符串常量池中初始化,而且只初始化一次,后续使用都会引用这个常量。

val1 = 字符串常量池引用 ===> 字符串本体(位于常量池中)
val2 = ↑

可以看到,val1val2的是同一个值,因此val1 == val2会返回true。

但是,当代码变成下面这样的时候:

String val1 = "val";
String val2 = new String("val");
// 输出为 false
System.out.println(val2 == val1);

上面的val2会在堆中新建一个对象,而不是常量池的对象,如下所示:

val1 = 字符串常量池引用 => 字符串本体(位于常量池中)
val2 = 字符串堆中对象引用 => 字符串本体(位于堆中)

因此两个引用的值并不相等。

如何正确使用.equals()

在上面的第二个例子中,很明显两个字符串是一样的,但是直接用==会得出false的结果,这时候就要使用equals了。
但是,.equals()使用也有要注意的地方:
当一个字符串常量和一个字符串变量比较时,要保持常量在前面。比如"张三".equals(name),而不是name.equals("张三")。这样可以保证在name 为null时,仍然可以获得比较的结果,如果反着写,就会得到一个空指针异常了。
当两个变量比较时,最好使用Objects.equals,比如比较两个名字是否一样,可以写成Objects.equals(name1,name2)Objects.equals会在内部调用对象的equals,并且会提前判断变量是否为空,防止出现空指针异常。