• 重写equals方法


     我们都知道,==是用来比较引用的(物理上的相等),而equals方法是用来比较值的(逻辑上的相等),在许多时候需要重写equals方法来实现我们的需求,比如把对象放到容器中,然后去查找对象。

    在重写equals 方法时要遵循一些契约:

    • 自反性:对于非空引用x而言,x.equals(x) 必须为true
    • 对称性:对于非空引用x和y,如果x.equals(y)为true,那么y.equals(x)必须也为true
    • 传递性:对于非空引用x,y和z,如果x.equals(y)为true,并且y.equals(z)为true,那么x.equals(z)必须也为true
    • 持久性:对于非空引用x和y,如果x.equals(y) 为true,那么当在x和y并未被修改的情况下,无论执行多少次x.equals(y),这个结果都为true
    • null-false: 对于非空引用x,x.equals(null) 始终为false

    反例:

    破坏自反性

     1 public class AntiReflexive {
     2 
     3     private String str;
     4     public String getStr() {
     5         return str;
     6     }
     7 
     8     public void setStr(String str) {
     9         this.str = str;
    10     }
    11     
    12     public boolean equals(Object o) {
    13         if (!(o instanceof AntiReflexive)) {
    14             return false;
    15         }
    16         
    17         AntiReflexive ar = (AntiReflexive)o;
    18         return this.str.equals(ar.str.toLowerCase());   // tolowercase 导致了自反性的破坏
    19     }
    20     
    21     public static void main(String[] args) {
    22         AntiReflexive ar1 = new AntiReflexive();
    23         ar1.setStr("Hello world");
    24         
    25         System.out.println(ar1.equals(ar1));
    26     }
    27 }
    View Code

    破坏对称性

     1 /**
     2  * 代码来自  effective java
     3  */
     4 public class AntiSymmetric {
     5 
     6     public static void main(String[] args) {
     7         CaseInsensitiveString cis = new CaseInsensitiveString("abc");
     8         String str = "abc";
     9         System.out.println(cis.equals(str));
    10         System.out.println(str.equals(cis));
    11     }
    12 }
    13 
    14 class CaseInsensitiveString {
    15 
    16     private String s;
    17     
    18     public CaseInsensitiveString(String s) {
    19         this.s = s;
    20     }
    21     
    22     public boolean equals(Object o) {
    23         if (o instanceof CaseInsensitiveString) {
    24             return s.equalsIgnoreCase(((CaseInsensitiveString)o).s);
    25         }
    26         
    27         if (o instanceof String) {        // 这个地方破坏了对称性,因为在String中不存在这样的逻辑,单向的
    28             return s.equalsIgnoreCase((String)o);
    29         }
    30         
    31         return false;
    32     }
    33 }
    View Code

    破坏传递性

     1 public class AntiTransitive {
     2 
     3     public static void main(String[] args) {
     4         ColorPoint x = new ColorPoint(10,  20, Color.red);
     5         Point y = new Point(10, 20);
     6         ColorPoint z = new ColorPoint(10,  20, Color.blue);
     7         
     8         System.out.println("x.equals(y) = " + x.equals(y));
     9         System.out.println("y.equals(z) = " + y.equals(z));
    10         System.out.println("x.equals(z) = " + x.equals(z));
    11     }
    12 }
    13 
    14 class Point {
    15     private int x;
    16     private int y;
    17     
    18     public Point(int x, int y) {
    19         this.x = x;
    20         this.y = y;
    21     }
    22     
    23     public boolean equals(Object o) {
    24         if (!(o instanceof Point)) {
    25             return false;
    26         }
    27         
    28         Point p = (Point)o;
    29         
    30         return x == p.x && y ==  p.y;
    31     }
    32 }
    33 
    34 class ColorPoint extends Point {
    35     private Color color;
    36     
    37     public ColorPoint(int x, int y, Color color) {
    38         super(x, y);
    39         this.color = color;
    40     }
    41     
    42     public boolean equals(Object o) {
    43         if (!(o instanceof Point)) {
    44             return false;
    45         }
    46         
    47         if (!(o instanceof ColorPoint)) {
    48             return o.equals(this);            // 这个地方破坏了传递性
    49         }
    50         
    51         ColorPoint cp = (ColorPoint)o;
    52         
    53         return super.equals(o) && cp.color == this.color;
    54     }
    55 }
    View Code

    在编写equals代码时,一些好的习惯是非常必要的

    • 使用 == 判断对象是否就等于this,这样就保证了自反性,还提高了performance
    • 使用instanceof 来判断这个对象是不是正确的类型,如果不是,就返回false
    • 将参数强制转换为正确的类型,因为经过了instanceof的测试,索引放心的转吧
    • 优先比较导致返回false的可能性比较大的字段,只要发现不一样就返回false
    • 对于float和double类型的字段,使用Float.compare 或者 Double.compare 方法来比较
    • 对于数组字段,遍历数组比较其中的每一项
    • 不要比较冗余字段(比如多边形类型的面积字段,就不用比较) 
    • 如果重写了equals,请重写hashcode
  • 相关阅读:
    three.js 加载外部模型的几种方法及格式
    使用httpserver开启一个本地服务器
    C#入门经典第4版 19章web编程基础 19.1~19.5代码(1)——default.aspx default.aspx.cs
    C#入门经典第4版 19章web编程基础 19.1~19.5代码(2)——ResultPage.aspx ResultPage.aspx.cs RegistrationInformation.cs
    Raspberry 刻录后首次登录配置
    禁止Chrome自动转换域名HTTP到HTTPS
    [Cnoi 2021]
    web前端的学习03
    web前端的学习01
    web前端的学习06
  • 原文地址:https://www.cnblogs.com/cookiezhi/p/5743778.html
Copyright © 2020-2023  润新知