JAVA中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方法检测相应的元素是否相等。

来看几个字符串比较例子:

  1. String a = "abc";
  2. String b = "abc";
  3. String c = new String("abc");
  4. String d = new String("abc");
  5. System.out.println(a == b); // true 因为JAVA中字符串常量是共享的,只有一个拷贝
  6. System.out.println(a == c); // false a和c属于2个不同的对象
  7. System.out.println(a.equals(c)); // true 由于String对象的equals方法比较的是对象中的值,所以返回true。(和Object的equals方法不同)
  8. System.out.println(c==d); // false c和d虽然对象内的值相同,但属于2个不同的对象,所以不相等
  9. System.out.println(c.equals(d)); // true

简单的说,当比较字符串常量时,等于和equals返回的结果一样,当想比较字符串对象的值时用equals。

看一个equals的使用例子:

  1. package chapter05.EqualsTest;
  2. import java.util.*;
  3. public class EqualsTest {
  4. public static void main(String[] args) {
  5. Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);
  6. Employee alice2 = alice1; // reference the same object
  7. Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15);
  8. Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1);
  9. System.out.println("alice1 == alice2: " + (alice1 == alice2));
  10. System.out.println("alice1 == alice3: " + (alice1 == alice3));
  11. System.out.println("alice1.equals(alice3): " + (alice1.equals(alice3)));
  12. System.out.println("alice1.equals(bob): " + (alice1.equals(bob)));
  13. System.out.println(bob.toString());
  14. }
  15. }
  16. class Employee {
  17. public Employee(String n, double s, int year, int month, int day) {
  18. name = n;
  19. salary = s;
  20. GregorianCalendar calendar = new GregorianCalendar(year, month, day);
  21. hireDay = calendar.getTime();
  22. }
  23. public String getName() {
  24. return name;
  25. }
  26. public double getSalary() {
  27. return salary;
  28. }
  29. public Date getHireDay() {
  30. return hireDay;
  31. }
  32. public void raiseSalary(double byPercent) {
  33. double raise = salary * byPercent / 100;
  34. salary += raise;
  35. }
  36. @Override
  37. public boolean equals(Object otherObject) {
  38. // a quick test to see if the objects are identical
  39. if (this == otherObject)
  40. return true;
  41. // must return false if the explicit parameter is null
  42. if (otherObject == null)
  43. return false;
  44. // if the classed don't match,they can't be equal
  45. if (getClass() != otherObject.getClass())
  46. return false;
  47. // now we know otherObject is a non-null Employee
  48. Employee other = (Employee) otherObject;
  49. // test whether the fields hava identical values
  50. return name.equals(other.name) && salary == other.salary
  51. && hireDay.equals(other.hireDay);
  52. }
  53. @Override
  54. public int hashCode() {
  55. return 7 * name.hashCode() + 11 * new Double(salary).hashCode() + 13
  56. * hireDay.hashCode();
  57. }
  58. @Override
  59. public String toString() {
  60. return getClass().getName() + "[name=" + name + ",salary=" + salary
  61. + ",hireDay=" + hireDay + "]";
  62. }
  63. private String name;
  64. private double salary;
  65. private Date hireDay;
  66. }
  67. class Manager extends Employee {
  68. public Manager(String n, double s, int year, int month, int day) {
  69. super(n, s, year, month, day);
  70. bouns = 0;
  71. }
  72. @Override
  73. public double getSalary() {
  74. double baseSalary = super.getSalary();
  75. return baseSalary + bouns;
  76. }
  77. public void setBouns(double b) {
  78. bouns = b;
  79. }
  80. @Override
  81. public boolean equals(Object otherObject) {
  82. if (!super.equals(otherObject))
  83. return false;
  84. Manager other = (Manager) otherObject;
  85. // super equals checked that this and other belong to the same class
  86. return bouns == other.bouns;
  87. }
  88. @Override
  89. public int hashCode() {
  90. return super.hashCode() + 17 * new Double(bouns).hashCode();
  91. }
  92. @Override
  93. public String toString() {
  94. return super.toString() + "[bouns=" + bouns + "]";
  95. }
  96. private double bouns;
  97. }

(0)

相关推荐

  • 为什么重写equals方法,还必须要重写hashcode方法

    原因: 1.为了提高效率. 采取重写hashcode方法,先进行hashcode比较,如果不同,那么就没必要在进行equals的比较了,这样就大大减少了equals比较的次数,这对比需要比较的数量很大 ...

  • 一次List对象去重失败,引发对Java8中distinct()的思考

    list的转map的另一种猜想 Java8使用lambda表达式进行函数式编程可以对集合进行非常方便的操作.一个比较常见的操作是将list转换成map,一般使用Collectors的toMap()方法 ...

  • java 集合中Set接口、数据结构

    集合中Set接口.数据结构 .Set接口 实现类 HashSet HashSet的特征 LinkedHashSet TreeSet 自然排序 数据结构 哈希表 哈希冲突 散列算法 二叉树 .Set接口 ...

  • 所有类的父类 Java Object

    Java Object 一.什么是Java Object 二.Object类的方法 1.创建并返回一个对象的拷贝protected Object clone() 2.比较两个对象是否相等 boolea ...

  • 吊打面试官系列:说说hashCode和equals方法

    首先我们需要知道hashCode方法和equals方法都是属于Object类的方法.既然属于Object中public修饰的方法,那言外之就是所有对象默认都有这两个方法,只是有时候有的对象已对这两个方 ...

  • java中equals,hashcode和==的区别

    java中equals,hashcode和==的区别 1.== java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型 byte,short,char,int,long,float,d ...

  • Java中String.split()用法说明

    在java.lang包中有String.split()方法,返回是一个数组.  1."."和"|"都是转义字符,必须得加"\\"; 如果用& ...

  • java中 equals 使用时的注意事项

    假设在比较 str 和 "hehe"两个字符串是否相等我们可以采用以下两种方式: (1) String str = null; if ("hehe".equal ...

  • Java教程- Java中hashCode与equals方法

    如何在父类中为子类自动完成hashCode和equals实现,这么做有什么优劣?说一下Object类中hashCode与equals方法的理解,在什么场景下需要实现这两个方法? 有没有可能两个不相等的 ...

  • 关于Java中static关键字的用法以及从内存角度解析

    在Java中,static可以用来修饰成员变量和成员方法. 修饰成员变量,称为静态成员方法 修饰静态方法,称为静态成员方法 搞清楚用法和区别之前,先搞清static声明的变量和普通非静态变量在内存的分 ...

  • java中BigDecimal加减乘除基本用法

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数. 在实际应用中,需要对更大或者更小的数进 ...

  • Java 中的关键字

    Java 中有多少个关键字,有大小写之分吗? Java 中有 48 个关键字在使用 + 两个保留关键字未使用,共 50 个关键字. Java 关键字全部都由是小写组成. Java 中保留关键字分别是哪 ...

  • Java中的匿名内部类

    一.匿名内部类 之前的所有类都有自己的名字,但是有时候如果某个接口的实现类(或者某个父类的子类)只需要使用一次,此时这样的类如果我们单独定义出来则需要单独为其创建一个"*.java" ...

  • 根管治疗中碘制剂的用法 :

    周佳齐医生: 给自己平时看资料的一个总结,希望都可以用的到. 根管治疗中碘制剂对于残髓的作用: 根管治疗过程中,常遇到残髓不容易清除干净的问题.我的经验是,先用碘酚导入根管,两分钟后用拔髓针试试,多数 ...