1. 面试问题:equals () 和 == 的区别是什么?

坑点分析

  • 新手仅笼统说 “== 比地址,equals 比值”,忽略 Object 类中 equals 的默认实现就是==

  • 漏提 String/Integer 等类重写 equals 的细节,也没说自定义类需重写 equals 的场景;

  • 混淆基本数据类型(无 equals 方法)和引用类型的==规则。

正确答案

① 作用对象:

  • ==:可比较基本数据类型(值是否相等),也可比较引用类型(内存地址是否相等,即是否指向同一对象);

  • equals():是 Object 类方法,仅能比较引用类型

② 实现规则:

  • Object 类中 equals 默认实现:return this == obj;(和==等价);

  • String、Integer、Date 等常用类重写了 equals,改为比较 “对象内容 / 值”;

  • 自定义类若需按内容比较,必须手动重写 equals(建议同时重写 hashCode,遵循 “相等对象必须有相等 hashCode”)。

    示例:

String s1 = new String("Java");
String s2 = new String("Java");
System.out.println(s1 == s2); // false(地址不同)
System.out.println(s1.equals(s2)); // true(内容相同)

2. 面试问题:String、StringBuffer、StringBuilder 的区别?

坑点分析

  • 仅提 “String 不可变,后两者可变”,漏了线程安全、性能核心维度;

  • 误以为 StringBuffer 性能和 StringBuilder 相当;

  • 忽略 String 常量池优化(如String s="a"+"b"会被编译为"ab",指向常量池)。

正确答案

核心围绕「可变性、线程安全、性能」三个维度:

维度

String

StringBuffer

StringBuilder

可变性

不可变

可变

可变

线程安全

天然安全

安全

不安全

性能

拼接频繁创建新对象

安全但性能低于StringBuilder

单线程下性能最高

适用场景

少量字符串操作

多线程字符串拼接

单线程大量字符串拼接

3. 面试问题:重载(Overload)和重写(Override)的区别?

坑点分析

  • 混淆判定规则:认为返回值不同能重载,或重写可修改参数列表;

  • 漏提重写的访问修饰符、异常抛出限制;

  • 不知道重载是 “编译时多态”,重写是 “运行时多态”。

正确答案

维度

重载(Overload)

重写(Override)

定义

同一类中,方法名相同、参数列表不同

子类重写父类方法,方法名 + 参数列表 + 返回值(协变)完全一致

核心判定

仅看参数列表(个数 / 类型 / 顺序)

方法签名(名 + 参数)必须完全一致

返回值

无要求(可不同)

需兼容(如父类返回 Object,子类可返回 String)

访问修饰符

无限制

子类不能缩小父类方法访问范围(如父类 public,子类不能 private)

异常抛出

无限制

子类不能抛出更宽泛的 Checked Exception

多态类型

编译时多态

运行时多态

点击下方小卡片免费获取Java资料Java资料https://mp.weixin.qq.com/s/iBmSycbmeTCSRNKJQ10EuA

4. 面试问题:HashMap 和 Hashtable 的区别?

坑点分析

  • 仅说 “Hashtable 线程安全,HashMap 不是”,漏了 null 键值、初始容量、扩容机制;

  • 误以为 HashMap 完全不能用于并发场景,没提 ConcurrentHashMap 的替代方案;

  • 不知道 Hashtable 是遗留类,已被淘汰。

正确答案

HashMap 是 Hashtable 的替代方案(JDK1.2 引入),核心区别:

① 线程安全:

  • Hashtable:方法加 synchronized,线程安全但并发效率低(全局锁);

  • HashMap:非线程安全,并发场景优先用 ConcurrentHashMap(分段锁 / CAS,效率更高)。

② null 支持:

  • Hashtable:不允许 key/value 为 null,否则抛 NPE;

  • HashMap:允许 1 个 null key,多个 null value。

③ 容量与扩容:

  • Hashtable:默认初始容量 11,扩容为原容量*2+1

  • HashMap:默认初始容量 16,扩容为原容量*2(必须是 2 的幂)。

④ 底层实现:JDK8 后 HashMap 引入红黑树(链表≥8 时),Hashtable 始终是数组 + 链表。

5. 面试问题:线程中 sleep () 和 wait () 的区别?

坑点分析

  • 核心误区:认为 sleep () 会释放锁;

  • 漏了所属类、唤醒方式、使用场景的区别;

  • 不知道 wait () 必须在同步代码块中调用,sleep () 无此要求。

正确答案

维度

sleep()

wait()

所属类

Thread 类(静态方法)

Object 类(所有对象拥有)

锁释放

不释放持有的锁

必须在 synchronized 中调用,调用后立即释放锁

唤醒方式

休眠时间到自动唤醒 / 被 interrupt () 中断

需 notify ()/notifyAll () 唤醒,或 wait (long) 超时自动唤醒

适用场景

固定时间休眠(如定时任务)

线程间通信(如生产者消费者模型)

6. 面试问题:Integer a=127, b=127; a==b 为 true?128 呢?为什么?

坑点分析

  • 仅知道结果,说不出底层的自动装箱缓存机制;

  • 混淆 int(基本类型)和 Integer(包装类型)的==比较规则;

  • 不知道缓存范围可通过 JVM 参数调整。

正确答案

① 结果:a=127 时a==b→true;a=128 时a==b→false

② 核心原因:Integer 的自动装箱缓存(IntegerCache)

  • JDK 默认缓存-128~127之间的 Integer 对象;

  • 范围内赋值时,直接取缓存对象,==比较地址相等;超出范围则新建对象,地址不同。

③ 补充:

  • 比较值需用 equals ()(Integer 重写 equals,比较值);

  • 缓存上限(127)可通过-XX:AutoBoxCacheMax=xxx调整,下限固定 - 128。

    示例:

Integer a=128, b=128;
System.out.println(a==b); // false
System.out.println(a.equals(b)); // true

7. 面试问题:抽象类(Abstract Class)和接口(Interface)的区别?

坑点分析

  • 仅说 “抽象类单继承,接口多实现”,漏了 JDK8 + 接口的默认方法、静态方法;

  • 混淆成员变量 / 方法的修饰符规则;

  • 不知道抽象类有构造方法,接口无。

正确答案

JDK8 + 后核心区别:

维度

抽象类

接口

继承 / 实现

单继承

多实现

成员变量

任意修饰符(private/public 等)

JDK8 前:public static final;JDK8+:新增 private 静态变量

方法

可包含抽象 / 普通 / 静态 / 默认方法

JDK8 前:仅抽象方法;JDK8+:新增 default / 静态方法;JDK9+:新增 private 方法

构造方法

有(供子类调用)

设计理念

强调 “is-a” 继承(如 Animal→Dog)

强调 “has-a” 行为契约(如 Runnable)

8. 面试问题:try-catch-finally 中的 finally 块一定会执行吗?

坑点分析

  • 最大误区:认为 finally 永远执行;

  • 漏了导致 finally 不执行的特殊场景;

  • 不知道 finally 中 return 会覆盖 try/catch 的 return 值。

正确答案

finally 并非绝对执行,以下场景不执行:

① try/catch 块执行前,线程被终止(如调用System.exit(0)、JVM 崩溃、断电);

② try 块中调用Thread.stop()(已废弃)。

其他场景(如 try/catch 中有 return/break/continue),finally 都会在 “try/catch 的 return 前” 执行。

关键陷阱:finally 中有 return 会覆盖 try/catch 的 return 值:

public static int test() {
    try {
        return 1;
    } finally {
        return 2; // 最终返回2,覆盖try的return 1
    }
}

点击下方小卡片免费获取Java资料Java资料https://mp.weixin.qq.com/s/iBmSycbmeTCSRNKJQ10EuA

9. 面试问题:ArrayList 和 LinkedList 的区别?

坑点分析

  • 仅说 “ArrayList 是数组,LinkedList 是链表”,漏了场景化效率区别;

  • 误以为 LinkedList 增删一定比 ArrayList 快;

  • 忽略内存占用、遍历方式的影响。

正确答案

维度

ArrayList

LinkedList

底层结构

动态数组(扩容 1.5 倍)

双向链表

随机访问(get (index))

高效(O (1))

低效(O (n),需遍历)

尾部增删

高效(O (1),无扩容时)

高效(O (1))

中间增删

低效(O (n),移动元素)

高效(O (1),仅改指针)

内存占用

连续空间,有扩容冗余

每个节点存 prev/next,开销更大

适用场景

频繁随机访问、少量增删

频繁中间增删、少量访问

关键提醒:LinkedList 增删快的前提是 “已找到目标节点”,若需先遍历找节点,效率反而低于 ArrayList。

10. 面试问题:Java 异常体系?Checked 和 Unchecked Exception 的区别?

坑点分析

  • 混淆两类异常的定义和处理规则;

  • 误以为 RuntimeException 必须捕获;

  • 漏了异常体系的继承结构(Throwable→Error/Exception)。

正确答案

① 异常体系核心结构:

Throwable(顶层)
├─ Error(如OOM、StackOverflowError):JVM严重错误,程序无法处理,无需捕获;
└─ Exception
   ├─ Checked Exception(如IOException、SQLException):编译时必须处理(捕获/抛出);
   └─ Unchecked Exception(RuntimeException及其子类,如NPE、数组越界):编译无需处理,运行时抛出。

② 核心区别:

维度

Checked Exception

Unchecked Exception

编译检查

必须处理

无需处理

产生原因

外部环境问题(文件不存在)

程序逻辑错误(空指针)

总结

  1. Java 面试陷阱题核心集中在细节规则(如 Integer 缓存、finally 执行逻辑)、易混淆概念(重载 / 重写、抽象类 / 接口)、锁与线程安全(sleep/wait、HashMap/Hashtable)三大类;

  2. 回答陷阱题时,不仅要给结论,还要解释底层原因(如缓存机制、锁释放逻辑),体现对 Java 原理的理解;

  3. 比较类问题建议按 “维度拆解 + 适用场景” 回答,逻辑更清晰,易被面试官认可。

  4. 由于篇幅有限,更多资料内容请点击下方小卡片免费获取Java资料https://mp.weixin.qq.com/s/iBmSycbmeTCSRNKJQ10EuA

更多推荐