摘要:java 编程中比较两个对象是 否相同,用Object 的equals 方法 或“==” 符号进行比较,equals 方法和“==”是比较对象内存地址, 但在实际中,仅以两个对象内存 地址不同而判断它们不同是不够 的,需覆盖equals 方法,自定义 判断标准,本文将对覆盖equals 方法遵循的原则和技巧进行分析 和实现。 【关键词】对象比较覆盖 equals 1 java中对象的比较 在java 编程中,提供了两个比较两个对 象的方法,一是用“==”运算符比较两个对 象的内存地址。二是用Object 的equals 方法, 不覆盖直接使用也是对比对象内存地址。 我们编写一个人类和员工类,员工类是 人类的子类,我们先不覆盖equals 方法,调用 equals 方法时,比较对象地址。 (1)编写Person 类,关键代码: private String name; privateintage; public Person(String name, int age) { this.name = name; this.age = age; } (2) 编写Employee 类继承Person 类, 关键代码: privateintsalary; publicEmployee(String name, int age,int salary) { super(name, age); this.salary=salary; } (3)以上两个类均没有覆盖equals 方法, 调用使,比较内存地址,测试关键代码: Employee p2=new Employee(" 张三",9,10); Employee p3=new Employee(" 张三",9,10); System.out.println(p2.equals(p3)); 运行结果: false p2 和p3 是分别用new 关键字创建出来的, 是不同地址的对象,比较的结果是false。 2 覆盖java中的equals方法进行自定义 比较 上面例子中,有两个叫张三的对象,调 用没覆盖的equals 方法时,显示是不同对象, 假设我们业务上要求,只要他们年龄、名字、 工资相同,认为两个对象是相同的,即我们认 为这两个张三,是同一个人。 我们就覆盖equals 方法,自定义比较规则, 让其符合业务要求。 2.1 覆盖equals方法遵循的原则 java 语言规范中有要求, 如果要覆盖 equals 方法,那么覆盖后的方法应该具有下面 几个的特点: (1)自反性:对于任何非空引用值 x, x.equals(x) 都应返回 true。 (2)对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y 才应返回 true。 (3)传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。 (4)一致性:对于任何非空引用值 x 和 y, 多次调用 x.equals(y) 始终返回 true 或 false, 前提是对象上 equals 比较中所用的信息没被修 改。对于任何非空引用值 x,x.equals(null) 都 返回 false。 2.2 覆盖equals方法 (1)覆盖person 的equals 方法,关键代码: a. 所有的对象和NULL 比较都是false if(obj==null){ returnfalse; } b. 下面小段代码遵循了自反性一致性 if(this==obj){ returntrue; } c. 下面小段代码遵循、对称性、传递性、 一致性 if(this.getClass()!=obj.getClass()){ returnfalse; } Person p=(Person)obj; if(this.age!=p.age){ returnfalse; } if(!this.name.equals(p.name)){ equals returnfalse; } returntrue; 上面的equals 方法中用getClass 实现,比 较的是同类型,不在父子类对象间比较(子类 中没有比较的属性除外),所以这里的equals 方法不能用于Person 类对象和子类对象的比 较。 (2) 覆盖Employee 的equals 方法, 关 键代码: if(this.getClass()!=obj.getClass()){ returnfalse; } a. 调用子类equals 方法要调用父类equals 方法,但如果父类是Object,则不要调用其父 类的equals 方法。 b. 比较父类里面的而子类没有声明的属 性 if(!(super.equals(obj))){ returnfalse; } Employee e = (Employee)obj; if(salary != e.salary){ returnfalse; } returntrue; (3)运行测试代码。 运行结果 true 按照业务要求,两个对象都具有相同的 名字、年龄、工资,所以是相同的。 3 小结 覆盖equals 方法一定要遵循以上的原则, 如果需要比较子类和父类的对象,还要进一步 改进equals 方法,还建议覆盖hashcode 方法, 比如HashSet 容器比较需要同时用到hashcode 和equals 方法。 参考文献 [1] 林信良编著. Java JDK 7 学习笔记[M]. 清华大学出版社, 2012,05,01 [2]( 美) 霍斯特曼, 科内尔著.Java 核 心技术卷1 [M]. 机械工业出版社, 2014,01,01 [3]( 美) 埃克尔编著.Java 编程思想(第4 版) [M]. 机械工业出版社, 2007,06,01 工作单位 广东金融学院 广东省广州市 510521 |