哈喽,各位刷题小伙伴!Day1 的基本数据类型考点大家都掌握了吗?今天咱们直击 Java 面试高频核心题 ——== 和 equals 的区别,还有 hashCode 与 equals 的 “绑定关系”,这题几乎是面试必问,赶紧码住!

今日题目
  1. Java 中 == 运算符的作用是什么?
  1. equals 方法的默认实现和重写逻辑?
  1. hashCode 和 equals 之间有什么必须遵守的约定?
一、基础答案
  1. == 运算符的作用
    • 比较 基本数据类型:比较的是 值是否相等(如 int a=10; int b=10; a==b → true);
    • 比较 引用数据类型:比较的是 对象的内存地址是否相同(即是否指向同一个对象,如 String s1=new String("a"); String s2=new String("a"); s1==s2 → false)。
  1. equals 方法的本质
    • 默认实现:Object 类中的 equals 方法底层就是 ==,即比较对象地址(源码:public boolean equals(Object obj) { return (this == obj); });
    • 重写逻辑:大部分常用类(如 String、Integer)会重写 equals 方法,改为 比较对象的内容是否相等(如 String s1="a"; String s2="a"; s1.equals(s2) → true)。
  1. hashCode 与 equals 的约定(面试重点)
    • 核心原则:如果两个对象 equals 相等,那么它们的 hashCode 必须相等
    • 反向不强制:如果两个对象 hashCode 相等,equals 不一定相等(哈希冲突场景)。
二、深度拆解(面试加分项)
1. 为什么 String 重写了 equals 和 hashCode?

看 String 类的核心源码(简化版):


public class String {

    private final char value[];

// 重写equals:比较字符数组内容

    public boolean equals(Object anObject) {

        if (this == anObject) return true;

        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;

                }

                return true;

            }

        }

        return false;

    }

// 重写hashCode:根据字符内容计算哈希值

    public int hashCode() {

        int h = hash;

        if (h == 0 && value.length > 0) {

            char val[] = value;

            for (int i = 0; i.length; i++) {

                h = 31 * h + val[i];

            }

            hash = h;

        }

        return h;

    }

}

原因:String 常作为 HashMap 的 key,重写后:

  • equals 保证 “内容相同的 String 视为同一个键”;
  • hashCode 保证 “内容相同的 String 哈希值相同”,能快速定位到 HashMap 的同一个桶,提升查询效率。
2. 违反 hashCode 与 equals 约定的后果?

如果只重写 equals 不重写 hashCode,会导致:

class Person {

    private String name;

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

// 只重写equals:认为名字相同就是同一个人

    @Override

    public boolean equals(Object o) {

        if (this == o) return true;

        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        return Objects.equals(name, person.name);

    }

// 未重写hashCode:使用Object的默认实现(基于内存地址)

}

// 测试代码

Person p1 = new Person("张三");

Person p2 = new Person("张三");

HashMap String> map = new HashMap<>();

        map.put(p1, "程序员");

System.out.println(map.get(p2)); // 输出null,而非"程序员"

后果:HashMap 中会把 p1 和 p2 视为两个不同的 key,导致数据查询异常,违背 “相同内容的对象应作为同一个键” 的预期。

三、面试避坑提醒
  1. 比较字符串内容优先用 equals,别用 ==(除非确认是常量池中的对象);
  1. 自定义类重写 equals 时,必须同时重写 hashCode,否则会影响 HashMap、HashSet 等集合的使用;
  1. 重写 hashCode 时,尽量保证 “equals 相等的对象,hashCode 一定相等;equals 不相等的对象,hashCode 尽量不同”(减少哈希冲突)。
四、今日打卡

评论区留下你的答案:以下代码输出什么?✅

String s1 = "Java";

String s2 = new String("Java");

String s3 = s2.intern();

System.out.println(s1 == s2);

System.out.println(s1 == s3);

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

(提示:intern () 方法会将字符串存入常量池,返回常量池中的引用)

文末预告

Day3 预告:String、StringBuffer、StringBuilder 的区别?面试中如何回答性能对比和适用场景?明天不见不散~

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐