# equals()

equals() 只能用来判断两个对象是否相等,不能用于判断基本数据类型的变量。equals() 存在于 Object 类中,所以所有类都有 equals(),因为 Object 类是所有类的父类。

  1. public boolean equals(Object obj) {
  2. return (this == obj);
  3. }

根据类是否重写了 equals(),使用 equals() 有两种情况:

  • 未重写:使用的默认是 Object 类的 equals(),等价于通过 == 操作符比较。
  • 重写:如果两个对象的每个属性都相等,则返回 true,否则返回 false。 ```java class Person { public String name;

    public Person(String name) {

    1. this.name = name;

    } }

Person person1 = new Person(“bill”); Person person2 = new Person(“frank”); String string1 = new String(“ab”); String string2 = new String(“ab”);

System.out.println(string1.equals(string2)); // String类重写了equals方法,返回true System.out.println( person1.equals(person2)); // Person类没有重写equals方法,返回false

  1. <a name="Yk037"></a>
  2. ## | == 和 equals()
  3. - equals() 是方法,而 == 是操作符。
  4. - == 对于基本类型和引用类型的作用效果是不同的:
  5. - 对于基本数据类型,== 比较的是值;
  6. - 对于引用数据类型,== 比较的是对象的内存地址;
  7. > 因为 Java 只有值传递,所以,对于 == 来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址。
  8. ```java
  9. Integer i1 = 288;
  10. Integer i2 = 288;
  11. int i3 = 288;
  12. int i4 = 288;
  13. System.out.println(i1 == i2); // 比较引用数据类型,返回false
  14. System.out.println(i3 == i4); // 比较基本数据类型,返回true

| 重写 equals()

重写 equals() 的思路:

  • 检查是否为同一个对象的引用,如果是直接返回 true;
  • 检查是否是同一个类型,如果不时,直接返回 false;
  • 将 Object 对象进行转型;
  • 判断每个属性或关键域是否相等;

    1. public class EqualsExample {
    2. private int x;
    3. private int y;
    4. private int z;
    5. public EqualsExample(int x, int y, int z) {
    6. this.x = x;
    7. this.y = y;
    8. this.z = z;
    9. }
    10. @Override
    11. public boolean equals(Object obj) {
    12. if (this == 0) return ture;
    13. if (obj == null || obj.getClass() != this.getClass()) return false;
    14. EqualsExample that = (EqualsExample) obj;
    15. if (x != that.x) return false;
    16. if (y != that.y) return false;
    17. return z == that.z;
    18. }
    19. }

    # hashCode()

    hashCode() 定义在 Object 类中,所以任何类都包含 hashCode()。
    hashCode() 返回哈希值,但是因为计算哈希值具有随机性,所以两个值不同的对象可能计算出相同的哈希值。

    Object 的 hashCode() 是本地方法,是通过 C 或 C++ 实现的,通常用来将对象的内存地址转换为整数。

  1. /**
  2. * native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的HashMap。
  3. */
  4. public native int hashCode()
  5. /**

| hashCode() 和 equals()

hashCode() 和 equals() 的关系:

  • 两个对象的 hash 值相等,equals() 不一定返回 true(哈希碰撞)。
  • 两个对象的 hash 值不相等,equals() 一定返回 false。
  • equals() 返回 true 时,两个对象的 hash 值一定相等。

    重写 equals 方法时也需要重写 hashCode 方法,这是因为:必须保证 equals 方法判断两个对象相等时,hash 值也相等。

| 重写 hashCode()

重写 hashCode,可以使用 Objects.hash() 实现,通过类的所有属性值生成最终的 hash 值。

  1. @Override
  2. public int hashCode() {
  3. return Objects.hash(x, y, z);
  4. }

# toString()

返回类的名字实例的哈希值的 16 进制字符串,建议所有的子类重写 toString 方法。

  1. public String toString()

# clone()

  1. protected native Object clone() throws CloneNotSupportedException

| 重写 clone()

clone() 在 Object 中的权限修饰符为 protected,所以如果一个类不显式重写 clone(),那新建类时就不能调用该类实例的 clone() 方法。

  1. public class CloneExample {
  2. private int a;
  3. private int b;
  4. }
  5. CloneExample e1 = new CloneExample();
  6. CloneExample e2 = e1.clone(); // 报错
  7. // 'clone()' has protected access in 'java.lang.Object'

| 实现 Cloneable 接口

类在重写 clone() 时还需要实现 Cloneable 接口,如果一个类没有实现,就会抛出 CloneNotSupportedException。

  1. public class CloneExample {
  2. private int a;
  3. private int b;
  4. @Override
  5. public CloneExample clone() throws CloneNotSupportedException {
  6. return (CloneExample)super.clone();
  7. }
  8. }
  9. CloneExample e1 = new CloneExample();
  10. try {
  11. CloneExample e2 = e1.clone();
  12. } catch (CloneNotSupportedException e) {
  13. e.printStackTrace();
  14. }
  15. // out: java.lang.CloneNotSupportedException: CloneExample

# 参考

  1. CS-Note
  2. javacore,判等问题
  3. javaguide,object类