需要覆盖equals:如果类具有自己特有的“逻辑相等”概念,而且超类还没有覆盖equals以实现期望的行为,这时我们就需要覆盖equals方法。
不需要覆盖equals:用实例受控确保“每个值至多只存在一个对象”的类。枚举类型就属于这种类。对于这样的类而言,逻辑相同与对象等同是一回事。
Object类中的equals方法用于检测一个对象是否等于另一个对象。在Object类中,这个方法判断两个对象是否具有相同的引用,如果两个对象具有相同的引用,它们一定是相等的。从这点上看,将其作为默认操作也是合乎情理的。然而,对于多数类类说,这种判断并没有什么意义,例如,采用这种方式比较两个PrintStream是否相等就完全没有意义。然而,经常需要检测两个对象状态的相等性,如果两个对象的状态相等,就认为这两个对象是相等的。所以一般在自定义类中都要重写equals比较。
下面给出编写一个完美equals()方法的建议:
1)显式参数命名为otherObject,稍后需要将转换成一个叫other的变量
2)检测this与otherObject是否引用同一个对象:
if(this==otherObject) return true;
这条语句只是一个优化。实际上,这是一种经常采用的形式。因为计算这个等式要比一个一个地比较类中的域所付出的代价小的多。
3)检测otherObject是否为null,如果为null,返回false。这项检测是很必要的。
if(otherObject==null) return false;
4)比较this和otherObject是否属于同一个类,如果equals的语义在每个子类中有所改变,就使用getClass()检测,它将自己作为目标类
if(getClass()!=otherObject.getClass()) return false;
如果所有的子类都拥有同一的语义,就使用instanceof检测
if(!(otherObject instanceof ClassName)) return false;
5)将otherObject转换为相应类型的变量:
ClassName other=(ClassName)otherObject;
6)现在开始对所有需要比较的域进行比较。使用==比较基本类型域,使用equals比较对象域。如果所有域都匹配,就返回true,否则返回false;
return field1==other.field1&&field2.equals(other.field2)
如果在子类中重新定义equals,就要在其中包含调用super.equals(other)。如果检测失败,就不可能相等。如果超类中的域相等,就比较子类中的实例域。
对于数组类型的域,可以使用静态的Arrays.equals方法检测相应的元素是否相等。
每个覆盖了equals方法的类中,也必须覆盖hashCode方法。
如果不这样的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap、HashSet和Hashtable。
在引用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一的返回同一个整数。在一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致。
如果连个对象根绝equals方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。
来看几个字符串比较例子:
- String a = "abc";
- String b = "abc";
- String c = new String("abc");
- String d = new String("abc");
- System.out.println(a == b); // true 因为JAVA中字符串常量是共享的,只有一个拷贝
- System.out.println(a == c); // false a和c属于2个不同的对象
- System.out.println(a.equals(c)); // true 由于String对象的equals方法比较的是对象中的值,所以返回true。(和Object的equals方法不同)
- System.out.println(c==d); // false c和d虽然对象内的值相同,但属于2个不同的对象,所以不相等
- System.out.println(c.equals(d)); // true
简单的说,当比较字符串常量时,等于和equals返回的结果一样,当想比较字符串对象的值时用equals。
看一个equals的使用例子:
- package chapter05.EqualsTest;
- import java.util.*;
- public class EqualsTest {
- public static void main(String[] args) {
- Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);
- Employee alice2 = alice1; // reference the same object
- Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15);
- Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1);
- System.out.println("alice1 == alice2: " + (alice1 == alice2));
- System.out.println("alice1 == alice3: " + (alice1 == alice3));
- System.out.println("alice1.equals(alice3): " + (alice1.equals(alice3)));
- System.out.println("alice1.equals(bob): " + (alice1.equals(bob)));
- System.out.println(bob.toString());
- }
- }
- class Employee {
- public Employee(String n, double s, int year, int month, int day) {
- name = n;
- salary = s;
- GregorianCalendar calendar = new GregorianCalendar(year, month, day);
- hireDay = calendar.getTime();
- }
- public String getName() {
- return name;
- }
- public double getSalary() {
- return salary;
- }
- public Date getHireDay() {
- return hireDay;
- }
- public void raiseSalary(double byPercent) {
- double raise = salary * byPercent / 100;
- salary += raise;
- }
- @Override
- public boolean equals(Object otherObject) {
- // a quick test to see if the objects are identical
- if (this == otherObject)
- return true;
- // must return false if the explicit parameter is null
- if (otherObject == null)
- return false;
- // if the classed don't match,they can't be equal
- if (getClass() != otherObject.getClass())
- return false;
- // now we know otherObject is a non-null Employee
- Employee other = (Employee) otherObject;
- // test whether the fields hava identical values
- return name.equals(other.name) && salary == other.salary
- && hireDay.equals(other.hireDay);
- }
- @Override
- public int hashCode() {
- return 7 * name.hashCode() + 11 * new Double(salary).hashCode() + 13
- * hireDay.hashCode();
- }
- @Override
- public String toString() {
- return getClass().getName() + "[name=" + name + ",salary=" + salary
- + ",hireDay=" + hireDay + "]";
- }
- private String name;
- private double salary;
- private Date hireDay;
- }
- class Manager extends Employee {
- public Manager(String n, double s, int year, int month, int day) {
- super(n, s, year, month, day);
- bouns = 0;
- }
- @Override
- public double getSalary() {
- double baseSalary = super.getSalary();
- return baseSalary + bouns;
- }
- public void setBouns(double b) {
- bouns = b;
- }
- @Override
- public boolean equals(Object otherObject) {
- if (!super.equals(otherObject))
- return false;
- Manager other = (Manager) otherObject;
- // super equals checked that this and other belong to the same class
- return bouns == other.bouns;
- }
- @Override
- public int hashCode() {
- return super.hashCode() + 17 * new Double(bouns).hashCode();
- }
- @Override
- public String toString() {
- return super.toString() + "[bouns=" + bouns + "]";
- }
- private double bouns;
- }
相关推荐
java_equals用法,用来熟悉重写equals方法的
Java 中 equals 和 == 的区别 Java 中的 equals 和 == 是两个不同的概念,很多开发者容易混淆它们。理解这两个概念的区别是非常重要的,因为它们对编程的正确性和性能都有很大的影响。 首先,我们需要了解 Java ...
### Java中equals方法隐藏的陷阱 在Java编程中,正确实现`equals`...通过遵循上述建议,可以有效地避免`equals`方法中的常见陷阱,并提高程序的质量。同时,了解这些陷阱背后的原理也有助于加深对Java语言特性的理解。
使用 intern() 方法可以将 s2 的值加入缓冲池中,这样可以避免创建新的字符串对象。 equals 和 == 是两个不同的运算符,它们之间的区别是非常重要的。我们应该根据实际情况选择合适的运算符,以避免编程中的错误。
在Java编程语言中,`equals()`方法和`==`运算符是两个经常被用来比较对象是否相等的关键概念。理解它们的区别对于编写出正确、健壮的代码至关重要。 首先,`==`运算符用于基本类型(如int, char, boolean)的比较,...
在Java编程语言中,了解如何正确使用`==`和`equals()`方法是非常关键的,因为它们在比较对象和基本类型时有不同的行为。下面将详细解释这两个方法的工作原理、使用场景以及一些常见误区。 首先,`==`运算符主要用于...
Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.
本文将深入探讨`equals`方法的使用方法、重写注意事项以及与`hashCode`方法的关系。 ### Q1. 何时应该重写`equals`方法? 在需要比较对象的值而不是引用时,应重写`equals`方法。默认情况下,`equals`方法使用`==`...
"Java中equals、hashcode和==的区别" Java 中 equals、hashcode 和==的区别是 Java 编程语言中一个经常遇到的问题。这三个概念都是用来比较对象的,但是它们之间存在着本质的区别。 首先,==号是Java中的一个...
在Java编程语言中,`equals`方法和`==`操作符都是用来比较对象之间是否相等的重要工具,但它们之间存在显著的区别。理解这些差异对于编写高效且无误的代码至关重要。 #### 二、基本概念 1. **==(双等号)**: - ...
在Java编程语言中,`equals`方法和`==`操作符都是用来比较对象之间是否相等的重要工具。然而,它们在实现这一目标的方式上有着本质的区别。理解这些差异对于正确地进行对象比较至关重要。 #### 二、基本概念 1. **...
在实践中,为了编写正确的`equals`方法,通常建议使用`Objects.equals()`和`Objects.hash()`方法,它们可以避免空指针异常,并简化代码。同时,`equals`方法和`hashCode`方法应当一起重写,以确保对象相等时其哈希码...
在 Java 中,equals() 方法和 == 操作符都是比较操作符,但是它们的用法和区别非常重要。equals() 方法用于比较对象的内容是否相等,而 == 操作符用于比较变量的值或地址值。在编写 Java 程序时,需要正确地使用这两...
例如,在 Java 中,String 类的 equals 方法用于比较两个字符串的内容是否相同: ```java String s1 = "Monday"; String s2 = "Monday"; if (s1.equals(s2)) { System.out.println("s1 equals s2"); } else { ...
### Java中的`==`与`equals`方法的区别详解 在Java编程中,比较对象的相等性是一个常见的需求,但很多初学者对于`==`运算符与`equals`方法的区别容易混淆。本文将深入探讨两者之间的差异,以及它们在不同场景下的...
在Java中,比较两个对象是否相等时,经常使用到的运算符有"=="和"equals"。虽然两者都可以用于比较,但它们有着本质的区别,特别是在比较对象和基本数据类型值时。 首先,我们来了解"=="运算符。在Java中,"==...
Java 中的equals和==的区别 Java 是一种面向对象的编程语言,其中有两种数据类型:基本数据类型和引用数据类型。基本数据类型包括整数...在编写 Java 代码时,需要根据具体情况选择使用 == 运算符或 equals 方法。
在equals()方法中,我们首先判断两个对象是否为同一个对象,然后判断obj对象是否为空,接着判断当前对象的类是否与obj对象的类相同,最后比较name成员变量是否相同。 在main方法中,我们创建了三个User对象:userA...