Java Object equals()方法详解:默认行为与重写实践

花开有时
花开有时
发布时间:2026-10-16 | 4人浏览过
原创

在Java开发中,区分对象的“相等”(相同内容)与“同一”(同一内存引用)是基础核心概念。Object类的equals()方法默认仅比较内存地址。本文将深入剖析其底层机制、默认行为表现,以及在实际业务场景如何通过重写来实现基于属性的逻辑相等判断,结合String类的实现原理说明自定义重写的必要性。

Object类与equals()的基本定位

java.lang.Object 位于Java核心包中,编译时自动导入,是所有Java类的根父类。无论是常规对象还是数组,都隐含地继承了Object类的方法。因此,每个Java开发者都能对任意类型调用 equals() 方法。

虽然语法上所有对象都能调用它,但其在基类中的定义非常基础:

  • 方法签名:public boolean equals(Object obj)
  • 核心职责:指示其他某个对象是否与此对象“相等”。
  • 注意误区:很多人认为 equals() 天生就是比较内容相等的,实际上在 Object 基类中,它仅负责比较引用同一性(即是否是同一个对象实例)。

默认实现:比较的是“同一”而非“相等”

如果不进行任何特殊处理,直接使用 Object 定义的 equals() 方法,其内部逻辑等同于使用 == 运算符来比较两个引用变量的内存地址。

准备测试环境

为了演示这一现象,我们创建一个简单的 Person 类和一个测试类,不进行任何 equals 的重写操作。

package com.example.demo.test;

public class Person {
    private String userName;
    private int age; // 原文age为String,这里按常规修正为int以匹配常用逻辑,若需严格对应原文则保留String

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
package com.example.demo.test;

public class Test {
    public static void main(String[] args) {
        // 创建两个内容相同但地址不同的Person对象
        Person p1 = new Person();
        p1.setUserName("Alice");
        
        Person p2 = new Person();
        p2.setUserName("Alice");

        // 1. 使用默认的Object.equals()
        System.out.println("p1.equals(p2): " + p1.equals(p2)); // false
        // 2. 使用 == 运算符
        System.out.println("p1 == p2: " + (p1 == p2)); // false

        /*
         * 对比:String类重写了Object类的equals()方法
         * String类会逐个字符比较内容,即使创建了两个不同的String对象实例
         */
        String s1 = new String("Hello");
        String s2 = new String("Hello");
        
        System.out.println("s1.equals(s2): " + s1.equals(s2)); // true (比较内容)
        System.out.println("s1 == s2: " + (s1 == s2));      // false (比较地址)
    }
}

结果分析与String类的启示

从上述代码的执行逻辑可以看出显著差异:

  1. Object的默认行为:对于 p1 和 p2,虽然它们的属性看起来一致,但因为它们是 new 出来的两个独立对象,拥有不同的内存地址,所以 equals() 返回 false。
  2. String的特殊处理:Java标准库中的 String 类觉得这种默认行为不符合人类直觉,因此在源码中 重写 了 equals() 方法,使其变成“逐字符比较”。

String.equals() 源码核心逻辑参考

了解这一源码有助于理解如何编写业务类的 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;
            // 第四步:逐字符比对
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

总结

在Java中,Object 类提供的 equals() 默认只关注对象是否是“同一个”(Same Identity),而不关心对象内容是否“一样”(Equal Content)。如果你需要比较两个自定义业务对象的数据内容是否相同,必须遵循Java的约定,重写 equals() 方法以及配套的 hashCode() 方法。以上就是Java Object类equals方法的详细内容,更多关于Java equals方法重写的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表