在Java中提供了两种比较变量或对象是否相等的方式,一是使用 == 运算符,二则是使用Object类的equals()方法,下面详细地为大家区别一下这两种方式的差异。
在这之前,我们有必要先来聊一聊变量和对象的产生过程。
对于变量而言,基本数据类型都保存在栈内存上,而引用数据类型(数组,接口,枚举,类,String)则保存在堆内存上。
基本数据类型的比较:
public class TestDemo1 {
public static void main(String[]args){
int a = 10;
int b = 10;
System.out.println(a == b);
}
}
运行结果如下:
引用类型(以String为代表)的比较:
public class TestDemo1 {
public static void main(String[]args){
String str = "i am groot";
String str1 = new String("i am groot");
System.out.println(str == str1);
}
}
运行结果如下:
这是因为在JVM底层实际上会⾃动维护⼀个对象池(字符串对象池,以下简称字符串常量池),如果现在采⽤了直接赋值的模式进⾏String类的对象实例化操作,那么该实例化对象(字符串内容)将⾃动保存到常量池之中。如果下次继续使⽤直接赋值的模式声明String类对象,此时常量池池之中如若有指定内容,将直接进⾏引⽤;如若没有,则开辟新的字符串对象⽽后将其保存在对象池之中以供下次使⽤;如果是采用了String类的构造函数的方式进行赋值的话,那么就是以创建对象的方式在堆内存上进行开辟空间了。
下面用图来抽象一下这个过程:
进行如下操作:
public class TestDemo1 {
public static void main(String[]args){
String str = "i am groot";
String str1 = new String("i am groot");
str1 = str; // 把str的地址给str1
System.out.println(str == str1);
}
}
运行结果如下:
此时发生如下关系:
由此可见,在Java中对 == 运算符的比较来说,如果比较的是基本类型的变量的话,那么比较的就是其值;如果比较的是引用类型的变量的话,那么比较的就是其引用的地址。
对于Object 类的 equals()方法主要是针对两个引用之间的比较(所以基本数据类型不能使用equals()方法进行比较),相当于直接比较引用的值。但是如果将基本数据类型的变量进行装箱操作变为包装类后,也可以用equals()方法进行比较。
仍然以上述代码为例:
public class TestDemo1 {
public static void main(String[]args){
Integer a = 10; // 自动装箱,底层调用 Integer.valueOf() 方法
Integer b = new Integer(10); // 显示装箱,不用调用 valueOf() 方法
System.out.println(a.equals(b));
System.out.println("==================");
String str = "i am groot";
String str1 = new String("i am groot");
System.out.println(str.equals(str1));
}
}
运行结果如下:
以上就是我对 == 和 equals()方法的理解和认识,如有不足或者错误,欢迎评论或私信指出,我会立刻改正,期待高手的点拨。