equals()方法详解
Java语言中equals()方法的使用可以说比较的频繁,但是如果轻视equals()方法,一些意想不到的错误就会产生。哈哈,说的有点严重了~
先谈谈equals()方法的出身。equals()方法在java.lang.Object类中声明,由于Object类是Java所有类的基类,因此equals()方法在Java中无所不在,我也是惊呆了。先贴一
段java.lang.Object类的英文说明:
Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class.
翻译一下:Object类是类继承树中的根类。每个类都把Object类作为其超类。所有的对象,包括数组,都实现了Object类所有的方法。
java.lang.Object类中的equals()方法如何声明的呢?源代码是这么写的:
public boolean equals(Object obj) {
return (this == obj);
}
稍微解释一下,这段代码就是说如果有 obj1.equals(obj2),那么返回值就是判断obj1和obj2堆地址是否相同(也就是说是否是同一块内存,即是否是同一个对象)。
阶段性总结一下java.lang.Object类的equals()方法:
1) equals()方法使用必须要有2个对象;
2) equals()方法返回的是一个boolean值,如果是同一个对象则返回true,否则返回false;
3) equals()方法本质还是使用了"=="双目运算符。("==":基本数据类型比较内容是否相同;引用数据类型比较对象hashCode是否相同,即引用指向的对象是否是同一个)。
摘自java.lang.Object类的equals()方法说明:equal objects must have equal hash codes
解释完Object类的equals()方法后,我试着用例题的形式来分析一下这些继承Object类的派生类equals()方法。一般来说Java核心类库中的类几乎都有equals()的重写,但是
自己写的类就没有重写咯。如果你没区别这两者就贸然使用equals()方法,那很可能还是在使用Object类的equals()方法。
类型一: Object类的派生类没有重写Object类的equals()方法
class MyClass{
int x;
MyClass(int i){
x=i;
}
public static void main(String[] args){
MyClass m1=new MyClass(100);
MyClass m2=new MyClass(100);
if(m1.equals(m2)){
System.out.println("Both are equal");}
else{
System.out.println("Both are not equal");
}
}
}
A代码编译时报出错误提示信息"equals()方法未定义"
B.编译通过,抛出运行期异常.
C.输出Both are equal.
D.输出Both are not equal
分析:做错这道题的原因很多,但是做对这题的原因只有一个,那就是真正理解了equals()方法的前因后果。本题中MyClass类隐继承了Object类(所有类的基类),但是并没
有重写Object类中的equals()方法。因此情况就是MyClass类和Object类的equals()方法是同一个,只不过MyClass类调用Object类的equals()方法而已。
public class MethodOverrideVsOverload {
public boolean equals( MethodOverrideVsOverload other ) {
System.out.println("MethodOverrideVsOverload equals method reached" );
return true;
}
public static void main(String[] args) {
Object o1 = new MethodOverrideVsOverload();
Object o2 = new MethodOverrideVsOverload();
MethodOverrideVsOverload o3 = new MethodOverrideVsOverload();
MethodOverrideVsOverload o4 = new MethodOverrideVsOverload();
if(o1.equals(o2)){
System.out.println("objects o1 and o2 are equal");
}
if(o3.equals(o4)){
System.out.println("objects o3 and o4 are equal");
}
}
}
输出结果为:
MethodOverrideVsOverload equals method reached
objects o3 and o4 are equal
分析:这道题不仅考察了"重写",也考察了"向上造型"现象。如果这道题做错,我感觉很可能是你认为下面这段代码是重写了java.lang.Object类的equals()方法。
public boolean equals( MethodOverrideVsOverload other ) {
System.out.println("MethodOverrideVsOverload equals method reached" );
return true;
}
其实不然,java.lang.Object类equals()方法的签名和这个方法的签名是不一样的,不一样在哪?一看就知道是参数列表嘛,两个字母差这么多呢~。所以啊,Object o1,o2
指向子类对象的情况并不是方法重写,只是发生了方法重载,o1和o2仍然会调用java.lang.Object类的equals()方法。不明白的建议温故一下方法重载(overload)&重写
(override)这两者。关于Java"向上造型"语法现象具体机制我会专门写一篇总结来解释的。
类型二:Object类的派生类重写了Object类的equals()方法
其实在Java Core Class Library中几乎都重写了java.lang.Object类的equals()方法。下面仅仅举2个常见的重写equals()方法的类。
(1) String类重写Object类的equals()方法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
下面分析一下String类equals()方法的源代码:
if (this == anObject) {
return true;
} // 这段其实就是Object类的翻版,功能一模一样
主要用于String类在constant pools(方法区常量池)的判断,如果是同一个对象那么就不用再判断两个对象是否内容相同了。写在开头是必须的,你说勒!
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false; // 一有内容不同就返回false
}
return true; // 字符串内容均相同则返回true
}
15 }
如果传入的是String类的对象,那么就是两个对象的内容比较,如果一有内容不同就返回false,均相同则返回true。
(2) Arrays类重写Object类的equals()方法
Arrays类的equals()方法有些区别,就是只加了static修饰符,当然这仍然是方法重写(只要派生类访问权限大于等于超类,派生类返回值类型是超类的子类,并且方法签名相
同,那么就可以方法重写)。而且Array类的equals()方法还重载了蛮多的,下面就举其中的long型(第一个)的例子加以说明:
public static boolean equals(long[] a, long[] a2) {
if (a==a2)
return true; // 如果数组引用指向同一个数组对象,那么显然是相同,返回true
if (a==null || a2==null)
return false; // 两个比较的数组不能是null
int length = a.length;
if (a2.length != length)
return false; // 如果两个数组不等长,显然也不可能相等
for (int i=0; i<length; i++)
if (a[i] != a2[i])
return false; // 如果两个数组等长,那么比较数组的元素,如果所有元素相同,那么这两个数组相同,反之不同
return true;
}
总结:
1) 对于equals()方法,无论如何都不能太轻视。在equals()内部其实也是有"=="在实现部分功能的。
2) 对于基本数据类型,"=="比较的变量的内容是否相同;对于引用数据类型,"=="比较的是对象的地址是否相同。
3) String类的equals()方法比较的是字符串是否内容相同。很多人误用,我猜可能就是这家伙惹的祸吧,嘻嘻~。
equals()方法详解的更多相关文章
- java数组、java.lang.String、java.util.Arrays、java.lang.Object的toString()方法和equals()方法详解
public class Test { public static void main(String[] args) { int[] a = {1, 2, 4, 6}; int[] b = a; in ...
- toString()和equals()方法详解
一:toString()方法 Object中toString方法 public String toString() { return getClass().getName() + "@&qu ...
- Java提高篇——equals()与hashCode()方法详解
java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...
- java基础(十六)----- equals()与hashCode()方法详解 —— 面试必问
本文将详解 equals()与hashCode()方法 概述 java.lang.Object类中有两个非常重要的方法: public boolean equals(Object obj) publi ...
- equals()与hashCode()方法详解
java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...
- 【Java】equals()与hashCode()方法详解 (转)
java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...
- Java中的equals和hashCode方法详解
Java中的equals和hashCode方法详解 转自 https://www.cnblogs.com/crazylqy/category/655181.html 参考:http://blog.c ...
- 转:Java中的equals和hashCode方法详解
转自:Java中的equals和hashCode方法详解 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这 ...
- equals()方法和hashCode()方法详解
equals()方法和hashCode()方法详解 1. Object类中equals()方法源代码如下所示: /** * Object类中的equals()方法 */ public boolean ...
随机推荐
- JavaScript高级程序设计学习笔记第五章--引用类型(函数部分)
四.Function类型: 1.函数定义的方法: 函数声明:function sum (num1, num2) {return num1 + num2;} 函数表达式:var sum = functi ...
- css3中变形处理
transfrom功能 在css3 中可以使用transfrom功能实现文字或图像的旋转,缩放,倾斜,移动等变形处理 deg是css3中使用的一种角度单位. 旋转: 使用rotate方法,在参数中加入 ...
- WPF ChangePropertyAction中TargetName和TargetObject的区别
在wpf页面布局中经常用到ChangePropertyAction来更改属性,在这个里面有TargetName和TargetObject两个属性,都表示需要修改的控件名称,那么这两个有什么区别呢,通过 ...
- yii使用CFrom调用ajax失败的记录
在学习配置yii的CFrom的时候,发现怎么也不能让ajax生效,后来看文档后 ,终于发现了问题的所在. 问题配置文件如下 public function getUserConfig(){ retur ...
- day11会话管理
会话管理入门 2.1 生活中会话 我: 小张,你会跳小苹果码? 小张: 会,怎么了? 我: 公司年会上要表演节目,你教教我把 小张:没问题,一顿饭而已. 我: OK. ........ 在这次生活中的 ...
- js函数定义参数个数和实际传入参数的对比
因为js是一种弱类型的编程语言,对数据类型的要求没有其他编程语言的要求严格,所以在定义函数的时候不需要像java和C#一样对其传入参数的类型进行定义.那么传入参数的个数有没有影响呢?今天小猪就做了个实 ...
- windows如何定时关闭一个程序
方法一其实系统本身有这项功能的,打开记事本,将以下内容保存为.bat文件(将下面cmd.exe的名字改成你的音乐播放软件的exe名)@echo offTASKKILL /F /IM cmd.exe / ...
- 51nod 1086【背包·DP】
思路: 如果体积乘以数量>=W,那么直接用完全背包模型.如果不到的话,用二进制优化就好了. 基础题,感觉这样写很优雅?回去睡觉. #include <bits/stdc++.h> u ...
- 渲染路径-surface shader 光照函数与渲染路径
https://docs.unity3d.com/Manual/SL-SurfaceShaderLighting.html Lighting Model declaration Lighting mo ...
- Jmeter接口自动化参数化 (转自软件测试部落)
测试场景: 有个查询城市(大概一百个 )天气预报的接口(需求参考第一课),需要根据不同的citycode,去查询对应城市的天气预报,这种接口该如何去测试呢? 分析需求: 不管是功能测试需求,还是接口测 ...