开场白
在Java家族里,“equals”与“==”是最容易让老铁混淆、分不清楚的一对表兄弟。为了便于大家提升对他们的辨识度,老铁专门对他们进行了采访,以下是采访实录。
老铁 :应广大老铁们要求,今天我们非常幸会请来了“equals”和“==”两位Java家族成员到“Java敲黑板系列”演播厅,欢迎两位!
equals :大家好,我是equals,感谢大家收看今天的“敲黑板系列”!
== :大家好,我是==,感谢大家收看今天的“敲黑板系列”!
老铁 :两位经常活跃在各大舞台,都是代码资深人士,也给大家留下了很深刻的印象。但是,大家很少有机会能非常全面的了解两位,并且很难得对两位进行一个横向的比较。首先,请两位分别介绍一下自己。
equals
身世之谜
首先来说说我的身世吧。大家都知道,在Java世界里面,有一个Object类,所有的其他类都继承于他,他就是Java所有类的父类或祖先类,Object类里面有一个equals方法,并且提供了默认的实现,如下代码片段所示。
public boolean equals(Object obj) {
return (this == obj);
}
最佳编程实践
敲黑板:从身世之谜中大家可以得知:如果一个自定义类没有覆盖equals方法,如代码片段1所示,那么该方法其实是用于判断两个对象是否是同一个对象。
当然,继承于Object的自定义类是可以覆盖equals方法的,但是覆盖的时候需要满足一些要求,以下通过一个例子来说明最佳编程实践,如下代码片段所示,代码注释中相关实践步骤说明。
public boolean equals(Object otherObject){
//1. 出于性能优化的考虑,首先判断是否是自身比较
if(this == otherObject) return true;
//2. 出于安全性的检测
if(null == otherObject) return false;
//3. 测试比较的对象是否是同一类型
if(!(otherObject.getClass() == this.getClass())) return false;
//4. 类型转换
PingPong other = (PingPong)otherObject;
//5. 根据业务需要对需要比较的成员变量进行逐一比较
//如果比较项都相同则返回为true
if(other.radius == this.radius) return true;
return false;
}
==符号
身世之谜
==是一个操作符,操作符的左右两边变量既可以是基本类型也可是对象类型。当==应用于基本类型的时候,是用于判断操作符左右两边的变量存储的值是否相等;当==应用于对象类型的时候是用于判断操作符左边的对象是否是同一对象。
案例说明
boolean ret;
int i1 = 2;
int i2 = 2;
float f1 = 2.0f;
float f2 = 2.0f;
double d1 = 2.0;
double d2 = 2.0;
String s1 = new String("abc");
String s2 = new String("abc");
String s3 = new String();
ret = (i1 == i2); //true
ret = (f1 == f2); //true;由于精度原因,不推荐
ret = (d1 == d2); //true;由于精度原因,不推荐
ret = (s1 == s2); //false
ret = (s1.equals(s2)); //true
ret = (s1.equals(s3)); //false
ret = (s1 == s2); //false
s3 = s1;
ret = (s1 == s3); //true
思考题
请老铁们考虑下面代码片段中的输出结果,答案将在下篇文章中揭晓。
String str1 = "敲黑板";
String str2 = "敲黑板";
String str3 = new String("敲黑板");
boolean ret;
ret = (str1 == str2); //?
ret = (str1.equals(str2)); //?
ret = (str1 == str3); //?
ret = (str1.equals(str3)); //?
ret = (str1 == str1.trim()); //?
小结
敲黑板,画重点:
- equals是类的成员方法,只能用于对象之间的比较,不能用于基本类型;
- ==既可以用于对象之间的比较,也可以用于基本类型。
- 如果一个自定义类不覆盖Object的equals方法,那么equals就是用于判断两个对象是否是同一个引用,意即是否是指向同一内存区域的首地址。
- 如果自定义类覆盖了Object的equals方法,那么则按照该方法自定义的业务逻辑进行判断,一般是用于判断两个对象的全部或部分内容是否相同。
- ==一方面可判断基本类型的值是否相等。Java基本类型包括了浮点型(float、double);整型(byte、short、int、long);字符型(char);布尔型(boolean)。但是,由于精度的问题,不建议==用于浮点型的比较,可采用两个浮点数相减并取绝对值,如果小于一个足够小的数(比如1.E-6)就认为是相等的。
- ==如果用于对象之间,则用于判断两者之间是否是同一个对象(此时与第3点中equals是可以互换的)。
彩蛋
NO.1 方法参数按“值”而非按“引用”方式传递 | Java敲黑板系列中留了一个思考题,其解答答案如下:
swap方法的参数p1和p2被初始化为pt1和pt2两个对象引用的拷贝,这个方法交换的是这两个拷贝,并没有改变存储在变量pt1和pt2中的对象引用;为此调用swap方法后,pt1和pt2变量的值并没有发生变化。
转载自公众号:代码荣耀