最近开始学习Java,学习到equals的用法时,与其他的语言类似,每次要进行比较时,基本上都是使用==,有时候也使用equals,==与equals之间有什么区别,一直都是模糊的,这次借助学习java的机会,总结一下,对==和equals有啦全面的认识了。
1、“==”属于关系操作符,就是用来比较值是否相等
看着==这个关系操作符很简单,还是要去细细地体会。
package equals;
public class EqualsTest {
public static void main(String[] args) {
int a=5;
int b=5;
double c=5;
String s1=new String("123");
String s2=new String("123");
System.out.println(a==b);//true
System.out.println(a==c);//true
System.out.println(s1==s2);//false
System.out.println(s1.equals(s2));//true
}
}
(1)对上面的结果,a==b和a==c都输出true,应该很容易理解,变量a、b、c都是基本类型,他们存储的值都是5,值相等。
在Java中有8中基本类型:
浮点型:double(8 byte),float(4 byte)
整型:byte(1 byte),short(2 byte),int(4 byte),long(8 byte)
字符型:char(2 byte)
布尔型:boolean(JVM规范没有明确规定其所占空间大小,但是明确指出其值只能取“true”“false”);
这8种基本类型对应的变量存储的是“值”,在用==比较时,就直接比较本身的“值”,注意:整型和浮点型都是有符号类型的,而char没有符号类型的。
(2)s1==s2输出false,现在我们就要看看基本类型变量和非基本类型变量的区别:
非基本类型变量也就是常说引用类型变量,如s1,s2就是引用类型变量。引用类型变量存储的不是“值”本身,而是存储的该变量对应的对象在内存中的地址。
引用类型变量s1与s2在内存中的分布如下:
001和002就是内存中s1与s2对应的地址(这里的001和002地址编号是举例说明的,具体地址分布请找度娘);
s1指向一个对象,引用类型变量s1存储的不再是“值”本身(“123”),而是s1指向的对象在内存堆中的地址,s2同理,因此,s1==s2输出一个false;对于s1.equals(s2)输出true,请继续向下看。
2、equals常见的使用--在Object中equals方法用于检测一个对象是否等于另一个对象,也就是判断这两个对象是否具有相同的引用。
(1)什么时候使用equals方法呢?
equals方法是超类Object中的方法,基本数据类型是没有的,因此只有比较对象是否相等的时候使用,即比较引用类型。
Object是超类,所有的类都默认继承自它。我们来看看Object类中equals方法的具体实现,具体路径:C:\Program Files\Java\jdk1.8.0_05\src\java\lang(根据自己jdk的路径),Object.java中,如下:
就这么一段代码,很显然,equals方法就是判断两个对象是否指向同一个引用。
但是,在使用的时候,往往会遇到困惑,如下:
package equals;
public class EqualsTest {
public static void main(String[] args) {
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1.equals(s2)); // 输入true
}
}
结果输出一个true,很显然嘛,s1和s2都是对象,即引用类型,s1与s2也指向不同的引用,按道理应该返回false。我们来看看String类中equal方法的具体实现,在String.java中,如下:
结果发现,String类中对equals方法进行了重写,比较指向的两个对象类型是否相等,在内存中所存储的内容是否相等。还发现,jdk类中不止这个类重写了equals方法,还有java.io.file,java.util.Date,java.lang.string,包装类(Integer,Double等)。
3、总结
对于==:如果比较基本数据类型的变量,直接比较其变量存储的“值”是否相等;
如果比较引用类型的变量,就比较其变量指向的对象在内存中的地址是否相等。
对于equals:不能用于基本数据类型的变量比较;
如果没有对equals方法进行重写,比较引用类型变量所指向的对象在内存中的地址;
如是java.io.file,java.util.Date,java.lang.string,包装类(Integer,Double等)类型,比较所指向的对象在内存中的内容。
个人觉得:为什么有了==还要有equals方法呢,==是基本的关系操作符,equals是一个方法,==这个关系操作符又不能进行重写,如果存在特殊情况的比较,就没有办法实现,因此就有equals方法出现,equals方法就可以进行重写,解决一些特殊情况的比较。然而==是达不到这个效果的。