JAVA面试-equals与==的本质区别
Java中与equals()的区别是面试和日常开发的核心知识点其核心差异在于比较的对象是比较引用地址或基本类型的值而equals()是比较对象的内容但其默认行为与重写密切相关 。为了清晰地理解我们可以将比较场景分为两大领域基本数据类型和引用数据类型。一、核心区别概览下表概括了和equals()在不同场景下的行为差异比较维度操作符equals()方法本质二元运算符Object 类中定义的方法比较目标基本类型比较值是否相等引用类型比较两个引用指向的内存地址堆地址是否相同引用类型默认行为与相同比较内存地址。多数类如 String、Integer会重写此方法用于比较对象的逻辑内容是否相等。使用场景判断两个变量无论是基本类型变量还是引用变量是否完全指向同一个对象。判断两个对象在业务逻辑上是否相等而不关心它们是否是同一个内存对象。二、分场景深度解析与代码示例1. 基本数据类型Primitive Types对于int,char,double,boolean等基本类型是唯一可用于比较的操作符它直接比较存储在变量中的值。而equals()是对象的方法基本类型无法调用。int a 100; int b 100; int c 200; System.out.println(a b); // true 因为值相等 System.out.println(a c); // false因为值不相等 // 以下代码无法编译因为基本类型没有 equals 方法 // System.out.println(a.equals(b)); // 编译错误2. 引用数据类型Reference Types这是理解两者区别的关键。所有类、数组、接口创建的变量都是引用类型。此时的比较行为是固定的而equals()的行为取决于其是否被重写 。的行为始终一致比较两个引用变量中存储的内存地址即是否指向堆中的同一个对象。equals()的行为分两种情况情况一未重写equals()例如自定义的类未重写。此时它继承自Object类的默认实现其逻辑就是比较内存地址与效果完全相同 。情况二已重写equals()例如String,Integer,Date等 JDK 常用类。此时比较的是对象的内容或状态。下面通过代码示例进行说明// 示例1自定义类未重写equals class Person { String name; public Person(String name) { this.name name; } } Person p1 new Person(Tom); Person p2 new Person(Tom); Person p3 p1; // p3 指向 p1 引用的同一个对象 System.out.println(p1 p2); // false p1和p2指向堆中两个不同对象 System.out.println(p1 p3); // true p1和p3指向同一个对象 System.out.println(p1.equals(p2)); // false Person类未重写equals默认调用Object的equals效果同 System.out.println(p1.equals(p3)); // true 同上本质是比较地址地址相同所以为true // 示例2String类已重写equals与常量池的影响 String s1 Hello; // 字面量s1指向字符串常量池中的Hello String s2 Hello; // 字面量s2同样指向常量池中已存在的Hello String s3 new String(Hello); // new关键字强制在堆中创建新对象 String s4 new String(Hello); System.out.println(s1 s2); // true! 因为s1和s2都指向常量池中的同一个Hello对象 System.out.println(s1 s3); // false s1在常量池s3在堆中是不同的对象 System.out.println(s3 s4); // false s3和s4是两个不同的堆对象 System.out.println(s1.equals(s2)); // true String重写了equals比较字符序列内容 System.out.println(s1.equals(s3)); // true 内容相同 System.out.println(s3.equals(s4)); // true 内容相同3. 特殊案例Integer的缓存机制JDK对部分包装类如Integer在-128到127范围内实现了缓存这会使得的比较结果出现“意外”这是理解与equals()区别的经典案例 。Integer i1 100; // 自动装箱实际调用 Integer.valueOf(100) Integer i2 100; // 命中缓存返回缓存中已有的同一个 Integer 对象 Integer i3 200; Integer i4 200; // 超出缓存范围new 新的 Integer 对象 System.out.println(i1 i2); // true! [-128,127] 内指向缓存中的同一对象 System.out.println(i3 i4); // false! 超出缓存范围是两个不同的对象 System.out.println(i1.equals(i2)); // true Integer重写了equals比较int值 System.out.println(i3.equals(i4)); // true 比较int值三、重写equals()的实践与规范如果希望自定义的类能够使用equals()进行有意义的逻辑比较必须重写equals()方法。重写时需要遵循通用约定自反性x.equals(x)必须返回true。对称性若x.equals(y)为true则y.equals(x)也必须为true。传递性若x.equals(y)为true且y.equals(z)为true则x.equals(z)也必须为true。一致性只要对象未被修改多次调用x.equals(y)应始终返回相同结果。非空性对于任何非null的xx.equals(null)必须返回false。一个典型的重写equals()的模板如下Override public boolean equals(Object obj) { // 1. 检查是否引用同一对象 if (this obj) return true; // 2. 检查参数是否为null以及是否为同一类型 if (obj null || getClass() ! obj.getClass()) return false; // 3. 将参数转换为当前类型 Person person (Person) obj; // 4. 比较关键字段此处比较name字段 // 注意String本身已正确实现了equals可以直接调用 return Objects.equals(name, person.name); // 使用Objects.equals可安全处理null }重要关联重写equals()必须同时重写hashCode()如果重写了equals()通常必须同时重写hashCode()方法这是为了满足hashCode的通用约定相等的对象必须具有相等的哈希码。这一点在使用HashMap、HashSet等基于哈希的集合时至关重要否则会导致对象在集合中行为异常。Override public int hashCode() { // 使用Objects.hash可以方便地基于多个字段生成哈希码 return Objects.hash(name); }总结在Java中是地址/值比较器行为确定equals()是逻辑相等比较器其行为由类定义决定。对于引用类型的逻辑比较应优先使用正确重写后的equals()方法而主要用于检查引用同一性。理解String常量池和Integer缓存等特例有助于在实际编码和问题排查中避免误区。参考来源总结一下java中我认识的哈希码以及equals和的区别java中 和 equelsequals 和 的区别java 中 equals 和 的区别常问到 equals 与 有什么区别equals和的区别
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2469665.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!