Java中equals与等号(==)的区别详解

陆景行
陆景行
发布时间:2026-10-14 | 6人浏览过
原创

在Java开发中,混淆 equals 方法与 == 运算符是初学者最常见的误区之一。本文将厘清两者在基本数据类型、复合数据类型(特别是 String)中的不同表现,揭示内存地址与对象内容的比较逻辑,并通过代码示例详解字符串常量池与 intern() 方法的应用场景。

核心概念:值比较 vs 引用比较

Java 的数据类型分为两类,其比较逻辑截然不同:

  1. 基本数据类型:byte, short, char, int, long, float, double, boolean。对于这些类型,== 直接比较存储在栈中的数值是否相等。
  2. 复合数据类型(类/引用类型):当使用 == 比较时,比较的是它们在堆内存中的存放地址(即引用是否指向同一个对象)。除非是两个变量指向 new 出的同一个对象实例,否则结果为 false。

所有 Java 类都继承自 Object 基类。Object 类中的 equals 方法初始行为也是比较对象的内存地址,因此默认情况下 == 与 equals 效果一致。然而,许多类库(如 String, Integer, Date)重写了 equals 方法,使其变为比较对象的内容而非地址。

实战案例:String类型的比较陷阱

为了直观理解差异,我们通过三个阶段的代码演示来分析 String 类型的比较行为。

第1步:字面量赋值与字符串池

当直接使用字符串字面量赋值时,JVM 会利用字符串常量池(String Constant Pool)进行优化。

public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = "Monday"; if (s1 == s2) { System.out.println("s1 == s2"); } else { System.out.println("s1 != s2"); } }} 

运行结果:s1 == s2

原理分析:s1 和 s2 引用的是内存中同一个 String 对象。JVM 首先在池中查找 "Monday",发现存在后直接将 s2 指向该实例,未创建新对象。

第2步:使用 new 操作符创建对象

若强制使用 new 关键字,则会绕过常量池的复用机制。

public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = new String("Monday"); if (s1 == s2) { System.out.println("s1 == s2"); } else { System.out.println("s1 != s2"); } if (s1.equals(s2)) { System.out.println("s1 equals s2"); } else { System.out.println("s1 not equals s2"); } }}

运行结果:s1 != s2
s1 equals s2

原理分析:

  • s1 引用池中的对象。
  • s2 使用 new 在堆内存中全新创建一个内容相同的对象。
  • == 比较地址,因对象不同,返回 false。
  • equals 比较内容,因字符串内容相同,返回 true。

第3步:利用 intern() 方法统一引用

有时我们需要确保特定字符串引用指向常量池中的唯一实例,此时可使用 intern() 方法。

public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = new String("Monday"); s2 = s2.intern(); if (s1 == s2) { System.out.println("s1 == s2"); } else { System.out.println("s1 != s2"); } if (s1.equals(s2)) { System.out.println("s1 equals s2"); } else { System.out.println("s1 not equals s2"); } }}

运行结果:s1 == s2
s1 equals s2

原理分析:intern() 方法检查字符串池中是否存在当前字符串。如果存在(如上例中 s1 已放入),则返回池中的引用;如果不存在,则将其添加到池中并返回引用。执行 s2 = s2.intern() 后,s2 被重新指向了常量池中已存在的 s1 对象,因此地址也相等了。

总结与建议

理解 == 与 equals 的关键在于区分“身份”与“内容”:

  • == 是操作符,比较基本类型的值或引用类型的地址(是否为同一实例)。
  • equals 是方法,默认比较地址,但在 String 等类中被重写为比较内容。

在业务开发中,若需判断两个字符串内容是否一致,应始终优先使用 equals() 或 Objects.equals(),避免使用 == 导致潜在的逻辑错误。

以上就是Java中equals和等号(==)的区别详解的详细内容,更多关于Java基础语法与对象比较的资料请关注本站其它相关文章!

本站声明

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

Python 相关产品和应用

全部下载

专题列表