Java中==与equals()的用法及区别总结

 更新时间:2026年05月18日 11:32:01   作者:莫寒清  
在Java编程中==运算符和equals方法是常用来比较对象或基本数据类型的重要工具,这篇文章主要介绍了Java中==与equals()的用法及区别总结的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

1. 一句话总结

  • ==基本类型比值引用类型比地址(判断是否指向堆中同一个对象)。
  • equals():是一个方法。默认实现(Object 类)也是比地址;但 String、包装类等通过重写实现了内容/逻辑相等的比较。

核心金句== 判断“是不是同一个”;equals() 判断“长得像不像”(取决于是否重写)。

2. 核心区别对比表

特性==equals()
本质Java 运算符Object 类的方法
比较内容基本类型比数值,引用类型比内存地址默认比地址,重写后比对象内容
可定制性不可重写,行为固定可以重写,自定义逻辑相等规则
适用范围任何基本类型或对象引用仅限对象(不能用于基本类型)
null 处理null == null 为 truenull.equals(...) 会抛 NPE

3.==的用法

3.1 基本类型比较(比较值)

int a = 10;
int b = 10;
System.out.println(a == b); // true

char c1 = 'A';
char c2 = 'B';
System.out.println(c1 == c2); // false

3.2 引用类型比较(比较地址)

String s1 = new String("Java");
String s2 = new String("Java");
String s3 = s1;

System.out.println(s1 == s2); // false(不同对象)
System.out.println(s1 == s3); // true(同一引用)

4.equals()的用法

4.1 默认行为:Object.equals()等同于==

public boolean equals(Object obj) {
    return (this == obj);
}

4.2 重写后的行为:比较内容/逻辑相等

String 重写了 equals(),比较字符串内容:

String s1 = new String("Java");
String s2 = new String("Java");

System.out.println(s1.equals(s2)); // true

5. 进阶高频考点(建议必背)

5.1 字符串常量池(String Pool)

面试常考:为什么 a == b 有时是 true,有时是 false?

String a = "abc";
String b = "abc";
String c = new String("abc");

System.out.println(a == b);       // true(常量池同一对象)
System.out.println(a == c);       // false(new 在堆上创建新对象)
System.out.println(a.equals(c));  // true(内容相等)

补充:

String d = c.intern();
System.out.println(a == d); // true(intern 返回常量池引用)

5.2 包装类缓存机制(Integer Cache)

IntegerShortByteCharacterLong(部分范围)存在缓存机制。

Integer x = 127;
Integer y = 127;
Integer m = 128;
Integer n = 128;

System.out.println(x == y);      // true  (缓存 -128~127)
System.out.println(m == n);      // false (超出缓存范围)
System.out.println(m.equals(n)); // true

结论:比较包装类型的值,优先用 equals()(或拆箱成基本类型再比 ==,注意 null 拆箱会 NPE)。

5.3equals()与hashCode()的契约(HashMap/HashSet 面试点)

  • 两个对象如果 equals()true,那么它们的 hashCode() 必须相同
  • HashMap/HashSet 的基本流程:先 hashCode() 定位桶,再 equals() 精确比较。
  • 如果只重写 equals() 不重写 hashCode():可能出现“放得进去、取不出来”或“重复放入”的问题。

6.equals()正确重写规则(契约)

  1. 自反性x.equals(x) 必须为 true
  2. 对称性x.equals(y)truey.equals(x) 也为 true
  3. 传递性x.equals(y)y.equals(z)truex.equals(z) 必须为 true
  4. 一致性:对象状态不变时,多次调用结果一致。
  5. 非空性x.equals(null) 必须为 false

7.instanceof还是getClass()?(加分点)

  • getClass():要求必须同一具体类才相等,更严格,较不易破坏对称性。
  • instanceof:允许子类参与比较,更灵活,但继承体系下容易破坏对称性/传递性。

8.null安全:避免 NPE 的写法(实用)

8.1 容易出错

String s = null;
System.out.println(s.equals("a")); // NPE

8.2 推荐写法

String s = null;
System.out.println("a".equals(s)); // false

或:

System.out.println(java.util.Objects.equals(s, "a")); // false(null-safe)

9. 一个规范的重写示例(可背模板)

import java.util.Objects;

public class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

10. 什么时候用==?什么时候用equals()?(面试收尾)

  • 基本类型:用 ==
  • 判断两个引用是否指向同一对象:用 ==
  • 判断对象内容(业务逻辑相等):用 equals()(并确保类正确重写 equals/hashCode)。
  • 比较 enum:推荐使用 ==(枚举天然单例,且语义明确)。

11. 常见追问补充(可选)

  1. StringBuilder / StringBufferequals():没有重写,仍是地址比较;要比内容用 toString()
  2. 数组的 equals():数组没有重写 equals(),比较地址;比内容用 Arrays.equals() / Arrays.deepEquals()
  3. 浮点数比较== 可能因精度误差不可靠,业务上常用误差范围(epsilon)比较。

总结 

到此这篇关于Java中==与equals()的用法及区别总结的文章就介绍到这了,更多相关Java ==与equals()区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • @DS注解的使用,动态数据源,事务详解

    @DS注解的使用,动态数据源,事务详解

    在项目中使用多数据源时,可以借助苞米豆的dynamic-datasource-spring-boot-starter进行配置,首先需引入相应的jar包,并在application.yml中设置主从数据源,其中一般选择master作为默认数据源,在实现类中通过@DS注解指定数据源
    2024-09-09
  • springboot解决Class path contains multiple SLF4J bindings问题

    springboot解决Class path contains multiple 

    这篇文章主要介绍了springboot解决Class path contains multiple SLF4J bindings问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • SpringCache框架加载/拦截原理详解

    SpringCache框架加载/拦截原理详解

    这篇文章主要介绍了SpringCache框架加载/拦截原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • SpringBoot项目将mybatis升级为mybatis-plus的方法

    SpringBoot项目将mybatis升级为mybatis-plus的方法

    本文主要介绍了SpringBoot项目将mybatis升级为mybatis-plus的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • Java棋类游戏实践之中国象棋

    Java棋类游戏实践之中国象棋

    这篇文章主要为大家详细介绍了Java棋类游戏中的中国象棋实现方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • jar更新jar包内的class以及修改class实现方式

    jar更新jar包内的class以及修改class实现方式

    文章主要介绍了使用jar命令操作JAR包的方法,包括解压、更新JAR包内的文件,以及直接修改JAR包内的Class文件等内容
    2026-04-04
  • MyBatis的SUM映射问题及解决

    MyBatis的SUM映射问题及解决

    这篇文章主要介绍了MyBatis的SUM映射问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • springboot 自定义属性与加载@value示例详解

    springboot 自定义属性与加载@value示例详解

    在SpringBoot框架中,自定义属性通常通过application.properties文件配置,并使用@Value注解加载,虽然这是一种可行的方法,但存在一种更优雅的实现方式,本文给大家介绍springboot 自定义属性与加载@value的相关操作,感兴趣的朋友一起看看吧
    2024-10-10
  • 基于Mybatis-Plus的CRUD的实现

    基于Mybatis-Plus的CRUD的实现

    这篇文章主要介绍了基于Mybatis-Plus的CRUD的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • java实现识别二维码图片功能方法详解与实例源码

    java实现识别二维码图片功能方法详解与实例源码

    这篇文章主要介绍了java实现识别二维码图片,java无法识别二维码情况下对二维码图片调优功能方法与实例源码,需要的朋友可以参考下
    2022-12-12

最新评论