Java中==和equals有什么不同是Java面试或笔试中经常看到的题目。这里为了更好的理解和记忆给出==和equals不同点、不同类中equals的源码是怎样的、==和equals测试代码3个方面。
Java中==和equals都有判断对象是否相等的作用,但是它们的用法并不相同。
==和equals不同点
- 属性不同:==是操作符;equals是方法。
- 用法不同:==比较的是地址或基本数据类型;equals比较的是对象的地址(对于String类型,equals比较的是String的内容)。
- 范围不同:==既可以比较基本数据类型和也可以比较引用数据类型;equals是方法只能比较引用数据类型。
注意:==两边是基本数据类型时,比较的是值是否相等,相等返回true,否则返回false;==两边比较的是引用类型时,则比较的是地址是否一样,相同地址则返回true,不同地址返回false。而equals比较的是对象的地址,对于String类型,equals比较的是String的内容。
equals的源码
下面给出Java中equals方法在各个类中的源码,其中String类中的比较若有不同。
String类中的equal()方法源码
public boolean equals(Object anObject) {
//判断是否是同一个对象,如果是的话就返回true
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
Object类中的equals方法源码
public boolean equals(Object obj) {
return (this == obj);
}
Byte包装类中equals方法源码
public boolean equals(Object obj) {
if (obj instanceof Byte) {
return value == ((Byte)obj).byteValue();
}
return false;
}
Short包装类中equals方法源码
public boolean equals(Object obj) {
if (obj instanceof Short) {
return value == ((Short)obj).shortValue();
}
return false;
}
==和equals代码测试
下面给出==和equals测试代码
//创建2个String对象
String s1 = new String("yxjc123");
String s2 = new String("yxjc123");
// == 比较的是2个地址,其中s1和s2在内存中的地址不同
System.out.println(s1==s2);//false
// equals方法在String中比较的是对象内容
System.out.println(s1.equals(s2));//true
String s3 = "yxjc123";
String s4 = "yxjc123";
// s3和s4都是引用数据类型,但"yxjc123"是保存在常量池中的,它们都指向的是常量池中同一个地址
// 所以 == 符号操作符 s3和s4相等
System.out.println(s3 == s4);//true
// 同样是比较两个地址,s3指向的是常量池中的地址,s1指向的是堆中的地址。
System.out.println(s3 == s1);//false
String s5 = "yxjc123yxjc123";
String s6 = s3 + s4;
// s5保存的是指向常量池的地址;s6保存的是指向堆中对应对象的空间,因为字符串是不可变对象,
// 无法直接通过相加而相连接,所以在进行相加操作时,实际上做的是:创建一个新的字符串对象,
// 通过 new StringBuilder()来创建。结果是false
System.out.println(s5 == s6);//false
final String s7 = "yxjc123";
final String s8 = "yxjc123";
String s9 = s7 + s8;
// final关键字修饰后,s7和s8都由变量变为了常量,编译器处理常量运算时会作出优化,
// 将运算后的结果转为常量, 然后再将常量结果赋给s9。下面语句结果为true
System.out.println(s9 == s5);//true
final String s10 = s3 + s4;
// s3 + s4是两个字符串对象相加,它们通过 new StringBuilder() 创建一个新的对象,然后
// 将此对象的地址给 s10, 然后final关键字将s10转为常量,但s10始终保存的是指向堆中的地址
// s5是指向常量池的地址。下面语句结果为false.
System.out.println(s5 == s10);//false