Java Object类与String相关高频面试题

Java Object类与String相关高频面试题


一、Object类有哪些方法?

核心回答(11个核心方法,按功能分类)

java.lang.Object 是Java所有类的顶级父类,所有类默认继承Object,核心方法如下:

方法 作用 核心考点
equals(Object obj) 判断两个对象是否相等 重写规则、与==的区别
hashCode() 返回对象的哈希码值 equals的契约、哈希表底层
toString() 返回对象的字符串表示 默认格式:类名@哈希码十六进制,建议重写
getClass() 返回对象的运行时Class对象 反射核心,final不可重写
clone() 创建并返回对象的副本 浅克隆/深克隆、需实现Cloneable接口
finalize() 对象被GC回收前调用 Java9已废弃,不推荐使用
wait() / wait(long timeout) / wait(long timeout, int nanos) 让当前线程等待,释放对象锁 线程通信、必须在synchronized中调用
notify() 唤醒一个等待该对象锁的线程 线程通信、随机唤醒
notifyAll() 唤醒所有等待该对象锁的线程 线程通信、全部唤醒

补充考点

  • getClass()notify()notifyAll()wait()final修饰,不能被重写
  • equals()hashCode()toString()clone() 是可重写的,也是面试高频考点
  • finalize() 仅执行一次,且不保证立即执行,Java 9 标记为废弃,Java 18 完全移除

二、==equals 有什么区别?

核心回答(分基本类型/引用类型)

1. == 的作用
  • 基本数据类型 :比较的是数值是否相等

    java 复制代码
    int a = 10;
    int b = 10;
    System.out.println(a == b); // true,数值相等
  • 引用数据类型 :比较的是对象的内存地址是否相等 (是否是同一个对象)

    java 复制代码
    String s1 = new String("abc");
    String s2 = new String("abc");
    System.out.println(s1 == s2); // false,两个不同对象,地址不同
2. equals() 的作用

equals() 是Object类的方法,默认实现和==完全一致 ,比较对象地址;

但很多类(如StringInteger)重写了equals(),改为比较对象的内容/值是否相等

java 复制代码
System.out.println(s1.equals(s2)); // true,String重写了equals,比较内容

核心区别总结

对比维度 == equals()
基本类型 比较数值 不能用于基本类型(只能用于对象)
引用类型 比较内存地址 默认比较地址,可重写为比较内容
可重写性 运算符,不可重写 方法,可重写
空值处理 null == null 为true null.equals(obj) 抛空指针异常

避坑示例(String常量池)

java 复制代码
String s1 = "abc"; // 常量池对象
String s2 = "abc"; // 复用常量池对象
System.out.println(s1 == s2); // true,地址相同
System.out.println(s1.equals(s2)); // true,内容相同

三、hashCode()equals() 方法有什么关系?

核心回答(哈希契约,面试必背)

hashCode()equals() 是Object类的两个核心方法,必须遵守以下契约 ,否则会导致哈希表(如HashMapHashSet)工作异常:

  1. 如果两个对象equals()相等,那么它们的hashCode()必须相等
  2. 如果两个对象hashCode()相等,equals()不一定相等(哈希碰撞)
  3. 重写equals()时,必须重写hashCode(),否则违反契约

原理说明

  • hashCode() 用于哈希表快速定位对象存储位置,equals() 用于最终确认对象是否相等
  • 哈希表的查找流程:先通过hashCode()定位桶位置,再用equals()在桶内遍历匹配
  • 若只重写equals()不重写hashCode(),两个内容相等的对象会有不同哈希码,导致HashSet认为是两个不同对象,存入重复数据

代码示例(正确重写)

java 复制代码
public class User {
    private String name;
    private int age;

    // 重写equals:比较内容
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age && Objects.equals(name, user.name);
    }

    // 必须同时重写hashCode
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

四、Java里String的常用方法有哪些?

核心回答(按功能分类,高频常用)

1. 长度/判空
  • length():返回字符串长度
  • isEmpty():判断字符串是否为空(长度为0)
  • isBlank()(Java 11+):判断字符串是否为空或仅含空白字符
2. 查找/获取
  • charAt(int index):获取指定索引的字符
  • indexOf(String str):返回子字符串第一次出现的索引,未找到返回-1
  • lastIndexOf(String str):返回子字符串最后一次出现的索引
  • substring(int beginIndex) / substring(int beginIndex, int endIndex):截取子字符串(左闭右开)
3. 转换/格式化
  • toLowerCase() / toUpperCase():转小写/大写
  • trim():去除字符串首尾空白字符(Java 11+推荐strip(),支持Unicode空白)
  • split(String regex):按正则表达式分割字符串
  • replace(char oldChar, char newChar) / replaceAll(String regex, String replacement):替换字符/字符串
  • valueOf(xxx):将其他类型转换为字符串(静态方法)
4. 比较/判断
  • equals(Object obj):比较字符串内容(区分大小写)
  • equalsIgnoreCase(String anotherString):比较内容(不区分大小写)
  • contains(CharSequence s):判断是否包含指定子字符串
  • startsWith(String prefix) / endsWith(String suffix):判断是否以指定前缀/后缀开头/结尾
5. 拼接
  • concat(String str):拼接字符串(比+效率高,底层直接数组复制)
  • join(CharSequence delimiter, CharSequence... elements)(Java 8+):用分隔符拼接多个字符串(静态方法)

五、String、StringBuffer、StringBuilder的区别和联系

核心回答(表格对比+原理)

1. 核心区别
对比维度 String StringBuffer StringBuilder
可变性 不可变(final修饰的char数组,Java9+为byte数组) 可变(可变数组,无final) 可变(可变数组,无final)
线程安全 安全(不可变,无并发修改) 安全(方法加synchronized修饰) 不安全(无锁)
性能 最低(每次修改都创建新对象) 中等(有锁开销) 最高(无锁,直接修改数组)
适用场景 少量字符串操作、常量 多线程环境下大量字符串操作 单线程环境下大量字符串操作
继承结构 实现SerializableComparableCharSequence 继承AbstractStringBuilder,实现CharSequence 继承AbstractStringBuilder,实现CharSequence
2. 核心原理
  • String不可变的原因 :底层存储用private final byte[] value(Java 9+),final保证数组引用不可变,且无对外修改数组的方法,因此每次修改(如concatsubstring)都会创建新的String对象,避免并发修改问题。
  • StringBuffer/StringBuilder可变的原因 :继承AbstractStringBuilder,底层用byte[] value(无final),可直接修改数组内容,无需创建新对象,性能更高。
  • 线程安全的区别 :StringBuffer的所有公共方法都加了synchronized,保证多线程安全,但带来锁开销;StringBuilder无锁,单线程下性能是StringBuffer的1.5~2倍。
3. 联系
  • 三者都实现了CharSequence接口,都表示字符序列
  • 都可以通过toString()转换为String对象
  • 核心操作(如appendinsertdelete)逻辑一致,仅线程安全和性能不同

代码示例(性能对比)

java 复制代码
// 单线程大量拼接:StringBuilder最快
long start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
    sb.append("a");
}
long end = System.currentTimeMillis();
System.out.println("StringBuilder耗时:" + (end - start) + "ms"); // 约1ms

// StringBuffer次之
start = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < 100000; i++) {
    sbf.append("a");
}
end = System.currentTimeMillis();
System.out.println("StringBuffer耗时:" + (end - start) + "ms"); // 约2ms

// String最慢
start = System.currentTimeMillis();
String str = "";
for (int i = 0; i < 100000; i++) {
    str += "a"; // 每次创建新对象,触发GC
}
end = System.currentTimeMillis();
System.out.println("String耗时:" + (end - start) + "ms"); // 约1000ms+

补充考点

  • String的常量池 :直接赋值的字符串会存入字符串常量池,复用对象;new String()会在堆中创建新对象,同时在常量池生成副本(Java 7+常量池移到堆中)
  • StringBuilder的初始容量 :默认初始容量16,当数组长度不足时,会按新容量 = 旧容量*2 + 2扩容,可通过new StringBuilder(1000)指定初始容量,避免频繁扩容
  • Java 9+的优化 :String、StringBuffer、StringBuilder底层从char[]改为byte[] + 编码标记,节省50%内存(Latin1字符仅占1字节)

六、面试答题技巧

  1. Object类方法 :先分类讲11个方法,重点讲equalshashCodewait/notify,体现对线程和哈希表的理解
  2. ==equals:分基本类型和引用类型,结合String常量池示例,讲清地址和内容的区别
  3. hashCodeequals契约 :强调"重写equals必须重写hashCode",结合HashMap的底层原理
  4. String常用方法:按功能分类,避免零散罗列,重点讲高频方法的使用场景
  5. String三兄弟区别:用表格对比,讲清可变性、线程安全、性能的核心差异,结合代码示例

相关推荐
Mr_Tony2 小时前
Swift 中的 Combine 框架完整指南(含示例代码 + 实战)
开发语言·swift
计算机学姐2 小时前
基于SpringBoot的宠物店管理系统
java·vue.js·spring boot·后端·spring·java-ee·intellij-idea
无心水2 小时前
22、Java开发避坑指南:日期时间、Spring核心与接口设计的最佳实践
java·开发语言·后端·python·spring·java.time·java时间处理
Hello.Reader2 小时前
双卡 A100 + Ollama 最终落地手册一键部署脚本、配置文件、预热脚本与 Python 客户端完整打包
开发语言·网络·python
Rsun045512 小时前
SpringBoot + Cursor 最佳提示词工程手册
java·spring boot·后端
cch89182 小时前
汇编VS C++:底层控制与高效开发之争
java·开发语言
openallzzz2 小时前
版本赶工期可临时扩容:模块开发、联调、交接一体化
java·摸鱼·外包
后端AI实验室2 小时前
裁员后我被迫负责运维,用AI从0搭建了可观测性平台
java·ai
lifewange2 小时前
代码托管平台
开发语言