Object 类是 Java 中所有类的祖先(根类)。面试中主要考察其中的核心方法以及与 String 相关的延伸问题。

1. Object 类有哪些常见方法?

面试官常让你列举 5-6 个,并问其中的细节。

  • getClass(): 获取对象的运行时类(反射入口)。
    • 它返回对象运行时的实际类对象,和编译时类型可能不同,而且这个方法不能重写。比如父类 Animal 的子类 Dog,Animal animal = new Dog,animal.getClass 返回的是 Dog 的类对象,
  • hashCode(): 获取对象的哈希码(用于 HashMap 等)。
  • equals(Object obj): 比较两个对象是否相等(默认比较地址)。
  • clone(): 创建并返回对象的一个副本(默认浅拷贝)。2. 如何实现深拷贝?
  • toString(): 返回对象的字符串表示(默认是 类名@哈希码)。
  • wait(): 让当前线程等待(释放锁)。
    • 同样需要在 synchronized 同步块或方法中使用,否则会抛 IllegalMonitorStateException.
  • notify() / notifyAll(): 唤醒等待的线程。
    • 比如生产者消费者模式中,生产者生产完数据后调用 notifyAll,唤醒等待的消费者线程。
  • finalize(): 垃圾回收前被调用(已不推荐使用)。

2** ==equals 的区别?(必考)

  • == (操作符):
    • 基本数据类型:比较是否相等。
    • 引用数据类型:比较内存地址是否相等(是不是同一个对象)。
  • equals (方法):
    • 默认行为(Object类):等价于 ==,比较内存地址。
    • 重写后(如 String, Integer):比较对象的内容是否相等。
    • 面试话术:== 对于引用类型比较的是地址,而 equals 默认也是比较地址,但通常我们会重写它来比较对象的内容,比如 String 就重写了 equals 来比较字符串里的字符。”StringBuilder / StringBuffer没重写哦

3.** hashCodeequals 的关系?(高频死穴)

面试官问:“为什么重写 equals 必须重写 hashCode?” 所谓“重写 hashCode”的意思是: 我们废弃掉 Java 原生那个“按内存地址生成整数”的逻辑,改为**“按对象的属性(比如 ID、名字)来生成整数”目的: 确保逻辑上相等的两个对象(比如 ID 都是 1 的两个 User 对象),在 HashMap 中能算出相同的索引位置**,从而能正确地存取数据。 这就是为什么面试官总是说:“重写 equals 时必须重写 hashCode”。如果不重写,你的对象在 HashMap 里就是个“隐形人”,存进去就再也找不到了。

  • 规定:
    1. 如果两个对象 equals() 为 true,那么它们的 hashCode() 必须相等
    2. 如果两个对象 hashCode() 相等,它们 equals() 不一定相等(这就叫哈希冲突)。
  • 为什么必须同时重写?
    • 这是为了配合 HashMap / HashSet 等散列表集合使用。
    • HashMap 存取数据是先算 hashCode 确定桶的位置,再用 equals 比较 key 是否相同。
    • 后果: 如果只重写 equals 不重写 hashCode,会导致“逻辑上相等”的两个对象(比如两个内容一样的 User 对象)生成的哈希码不同,被 HashMap 存到了不同的坑里,导致无法根据 key 取出 value,或者 HashSet 存入了重复数据。
class Student {
    String name;
    Student(String name) { this.name = name; }
    // 只重写了 equals,没重写 hashCode
    public boolean equals(Object o) {
        Student s = (Student) o;
        return this.name.equals(s.name);
    }
}
// 测试
HashMap<Student, String> map = new HashMap<>();
Student s1 = new Student("小林");
map.put(s1, "这是小林的数据");
Student s2 = new Student("小林"); // 新建一个一模一样的对象
System.out.println(map.get(s2)); // 输出 null (找不到!)
 
 
@Override
public int hashCode() {
    // 只要名字一样,算出来的整数就一定一样
    return Objects.hash(name); 
}
**结果:** `map.get(s2)` 就能成功输出 "这是小林的数据"

4. String 相关面试题

A. String 为什么是不可变的 (Immutable)?

  1. 底层实现: String 内部使用 private final char[] 数组存储字符(JDK9 后改为 byte[]),且没有暴露修改数组的方法。
  2. 安全性: 保证 HashMap 的 Key 不会被修改,保证线程安全,保证字符串常量池的运作。

B. String, StringBuffer, StringBuilder 的区别?

特性StringStringBuilderStringBuffer
可变性不可变可变可变
线程安全安全 (常量)不安全 (快)安全 (因为加了 synchronized)
性能差 (拼接产生新对象)最快中等
适用场景少量的字符串操作单线程大量拼接 (最常用)多线程大量拼接

C. intern() 方法有什么用?

  • 将字符串对象手动加入字符串常量池
  • 如果常量池中已经有了这个字符串,就直接返回常量池里的引用;如果没有,就放进去再返回。

5. Java 里 string的常用方法有哪些?

1. 比较与判断 (最常用)

  • equals(Object anObject): 比较两个字符串的内容是否完全相同(区分大小写)。
  • equalsIgnoreCase(String anotherString): 比较内容是否相同(忽略大小写)。
  • startsWith(String prefix): 判断是否以指定字符串开头。
  • endsWith(String suffix): 判断是否以指定字符串结尾。
  • contains(CharSequence s): 判断是否包含某个子串。
  • isEmpty(): 判断是否为空字符串 ""(长度为0)。
    • 注意: 开发中常用 StringUtils.isBlank() (Apache工具类) 来同时判断 null 和空字符串。

2. 获取与查找

  • length(): 返回字符串的长度。
  • charAt(int index): 获取指定索引位置的字符。
  • indexOf(String str): 查找子串第一次出现的索引(找不到返回 -1)。
  • lastIndexOf(String str): 查找子串最后一次出现的索引。
  • substring(int beginIndex): 截取从指定位置开始到末尾的子串。
  • substring(int beginIndex, int endIndex): 截取指定范围的子串(包头不包尾,即 [begin, end))。

3. 转换与替换

  • toLowerCase(): 转为全小写。
  • toUpperCase(): 转为全大写。
  • trim(): 去除字符串首尾的空格。
    • JDK 11 新特性: strip() (能去除更多种类的空白字符)。
  • replace(CharSequence target, CharSequence replacement): 替换所有匹配的子串。
    • 注意: replace 也是替换所有,不是替换第一个。
  • replaceAll(String regex, String replacement): 基于正则表达式替换所有匹配项。
  • split(String regex): 根据分隔符(支持正则)将字符串拆分成 String[] 数组。
  • toCharArray(): 将字符串转换为字符数组 char[]
  • getBytes(): 将字符串编码为字节数组 byte[](网络传输、IO常用)。

4. 格式化与静态方法

  • String.format(String format, Object... args): 类似 C 语言的 printf,用于格式化字符串(如 %s, %d)。
    • String s = String.format("Hi, %s", "Tom");
  • String.valueOf(Object obj): 将各种数据类型转为字符串(推荐用这个,因为它处理了 null,不会报空指针,而是返回字符串 “null”)。

6.总结表格

知识点核心回答要点
Object 方法重点掌握 equals, hashCode, wait, notify
== vs equals地址 vs 内容 (重写后)
Hash 契约equals 相等则 hash 必相等;hash 相等 equals 未必
String 三兄弟String 不可变;Builder 快但不安全;Buffer 慢但安全