关于equals的那些事

==和equals的区别是什么?

==比较的是两个对象在内存中的地址,equals比较的是两个对象的值。这个说法是片面的。

==的作用

==是专门用来比较两个变量是否相等的,即比较两个变量在内存中存储的数据值是否相等,比较两个基本数据类型或者两个引用变量是否相等时,只能用==

  • 变量:指可以改变的量,是内存中的一个空间(容器),用于存储数据
  • 引用变量:当一个变量指向的是对象类型的数据,那这个变量即引用变量
//obj为引用变量,存储的数据为new Object()这个对象在内存中的地址,并不是对象的值
Object obj = new Object();

equals的作用

  • Object类中的equals方法在比较是用的还是==,所以如果没有重写equals方法,它将继承Object类中的equals方法,相当于还是在使用==进行比较
    //Object类中的equals方法,是用==进行比较
    public boolean equals(Object obj) {
        return (this == obj);
    }
  • 对于重写过的equals方法,比较的是两个对象的值,如String中的equals方法
    //String源码中的equals方法
    public boolean equals(Object anObject) {
        //先用==比较,如果内存中的地址一样,则不再进行比较,直接返回true
        if (this == anObject) {
            return true;
        }
        //是String类型,才进行以下的比较
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                //通过循环比较字符串中每个字符的值是否相等,不相等则返回false
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        //其他情况则直接返回false
        return false;
    }
  • 对于基本数据类型的包装类,也是重写了equals方法,比较的是对象的值
    //以Integer为例,比较的是对象的值,其他基本数据类型的包装类也一样
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }
  • 自定义对象,如果重写了equals方法,则比较的是每个属性的值是否相等
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.yms.entity;

public class User {
  private String name;
  private Integer age;

  public User() {
  }

  public String getName() {
    return this.name;
  }

  public Integer getAge() {
    return this.age;
  }

  public void setName(final String name) {
    this.name = name;
  }

  public void setAge(final Integer age) {
    this.age = age;
  }

  public boolean equals(final Object o) {
    if (o == this) {
      return true;
    } else if (!(o instanceof User)) {
      return false;
    } else {
      User other = (User)o;
      if (!other.canEqual(this)) {
        return false;
      } else {
        Object this$age = this.getAge();
        Object other$age = other.getAge();
        if (this$age == null) {
          if (other$age != null) {
            return false;
          }
        } else if (!this$age.equals(other$age)) {
          return false;
        }

        Object this$name = this.getName();
        Object other$name = other.getName();
        if (this$name == null) {
          if (other$name != null) {
            return false;
          }
        } else if (!this$name.equals(other$name)) {
          return false;
        }

        return true;
      }
    }
  }

  protected boolean canEqual(final Object other) {
    return other instanceof User;
  }

  public int hashCode() {
    int PRIME = true;
    int result = 1;
    Object $age = this.getAge();
    result = result * 59 + ($age == null ? 43 : $age.hashCode());
    Object $name = this.getName();
    result = result * 59 + ($name == null ? 43 : $name.hashCode());
    return result;
  }

  public String toString() {
    return "User(name=" + this.getName() + ", age=" + this.getAge() + ")";
  }
}

为什么重写了equals方法就必须重写hashCode方法?

  • 在每个覆盖了equals方法的类中,都必须覆盖hashCode方法。如果不这样做的话,就会违反hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这列集合包括HashMap和HashSet。
  • 如果两个对象的值相等,那么它们对应的hashCode则一定相等,反过来则不一定,这就是我们所说的哈希冲突

对于equals的其他理解可参考Effective Java 第三版中第10条、第11条

        

### `equals` 方法的使用方式 在 Java 中,`equals` 方法主要用于比较两个对象的内容是否相等。对于 `String` 类,`equals` 方法比较的是字符串的实际内容,而不是引用地址。以下是一个简单的示例: ```java public class EqualsExample { public static void main(String[] args) { String str1 = "Hello"; String str2 = new String("Hello"); // 使用 equals 方法比较内容 boolean isEqual = str1.equals(str2); System.out.println("str1 和 str2 的内容是否相等: " + isEqual); // 使用 == 比较引用地址 boolean isSameReference = str1 == str2; System.out.println("str1 和 str2 是否引用同一对象: " + isSameReference); } } ``` 在上述代码中,`str1` 和 `str2` 的内容相同,但引用地址不同。使用 `equals` 方法比较时返回 `true`,而使用 `==` 比较时返回 `false`。这表明在实际的 Java 编程中,如果目的是比较两个字符串的内容是否相等,应该使用 `equals` 方法,而不是 `==` 运算符,因为 `equals` 方法比较的是字符串的实际内容,能够满足大多数场景下的比较需求[^1]。 ### 与字符串拼接对象打印的关联 在字符串拼接对象打印的场景中,`equals` 方法可以用于验证拼接结果是否符合预期。例如,在拼接对象的 `toString` 方法返回的字符串时,可以使用 `equals` 方法来检查拼接后的字符串是否与预期的字符串一致。以下是一个示例: ```java class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + "}"; } } public class StringConcatenationWithEquals { public static void main(String[] args) { Person person = new Person("Alice", 25); String expected = "This is a person: Person{name='Alice', age=25}"; String result = "This is a person: " + person; boolean isExpectedResult = result.equals(expected); System.out.println("拼接结果是否符合预期: " + isExpectedResult); } } ``` 在这个示例中,通过 `equals` 方法比较拼接后的字符串 `result` 和预期的字符串 `expected`,从而验证拼接结果是否正确。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值