跳到主要内容Java 核心面试题汇总及解析 | 极客日志Javajava
Java 核心面试题汇总及解析
Java 面试通常涉及基础语法、集合框架、多线程机制、JVM 等核心领域。本文整理了高频考点,包括 JDK 与 JRE 区别、equals 与 hashCode 规范、String 内存模型、HashMap 原理、线程状态与锁升级机制等。内容覆盖 IO 流、反射、设计模式及主流框架 Spring 相关知识点,旨在帮助开发者梳理知识体系,应对技术面试挑战。
Java 基础
1. JDK 和 JRE 有什么区别?
- JDK:Java Development Kit,开发工具包,提供开发环境和运行环境。
- JRE:Java Runtime Environment,运行环境,为 Java 程序运行提供支持。
简单来说,JDK 包含了 JRE。如果你需要编写 Java 程序,必须安装 JDK;如果只需要运行程序,安装 JRE 即可。
2. == 和 equals 的区别是什么?
== 解读
对于基本类型和引用类型,== 的作用效果不同:
- 基本类型:比较值是否相同。
- 引用类型:比较引用地址是否相同。
String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x == y);
System.out.println(x == z);
System.out.println(x.equals(y));
System.out.println(x.equals(z));
x 和 y 指向常量池中的同一个对象,所以 == 为 true;new String() 开辟了新的堆内存,所以 == 为 false。equals 默认比较的是引用,但 String 等类重写了该方法用于比较值。
equals 解读
Object 类的 equals 方法本质上就是 ==。看下面的代码就明白了:
class Cat {
public Cat(String name) { this.name = name; }
private String name;
public String getName() { return name; }
}
Cat c1 = new Cat();
();
System.out.println(c1.equals(c2));
"王磊"
Cat
c2
=
new
Cat
"王磊"
输出结果为 false,因为默认比较的是地址。而 String 重写了 equals 方法,将引用比较改成了内容比较。
总结:== 对基本类型比值,对引用类型比地址;equals 默认比地址,但多数类(如 String、Integer)重写了它来比值。
3. 两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?
不对。hashCode 相等只意味着哈希桶位置可能相同,不代表对象内容相等。
String str1 = "通话";
String str2 = "重地";
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
System.out.println(str1.equals(str2));
散列表中,哈希值相等即键值对的哈希值相等,但键值对不一定相等。
4. final 在 Java 中有什么作用?
- 修饰类:最终类,不能被继承。
- 修饰方法:最终方法,不能被重写。
- 修饰变量:常量,必须初始化且不可修改。
5. Java 中的 Math.round(-1.5) 等于多少?
等于 -1。Math.round 的原理是'加 0.5 向下取整'。数轴上取值时,中间值向右取整,正 0.5 往上取整,负 0.5 直接舍弃。
6. String 属于基础的数据类型吗?
不属于。基础类型有 8 种:byte、boolean、char、short、int、float、long、double。String 属于对象。
7. Java 中操作字符串都有哪些类?它们之间有什么区别?
主要有 String、StringBuffer、StringBuilder。
- String:不可变对象,每次操作生成新对象。
- StringBuffer:可变,线程安全,性能较低。
- StringBuilder:可变,非线程安全,性能高于 StringBuffer。
经常改变字符串内容时,推荐使用 StringBuilder(单线程)或 StringBuffer(多线程)。
8. String str="i"与 String str=new String('i')一样吗?
9. 如何将字符串反转?
使用 StringBuilder 或 StringBuffer 的 reverse() 方法。
StringBuilder sb = new StringBuilder();
sb.append("abcdefg");
System.out.println(sb.reverse());
10. String 类的常用方法都有那些?
- indexOf():返回指定字符索引。
- charAt():返回指定索引字符。
- replace():替换字符串。
- trim():去除两端空白。
- split():分割字符串。
- getBytes():转为 byte 数组。
- length():获取长度。
- toLowerCase()/toUpperCase():大小写转换。
- substring():截取子串。
- equals():比较内容。
11. 抽象类必须要有抽象方法吗?
不需要。抽象类可以没有抽象方法,但不能直接实例化。
12. 普通类和抽象类有哪些区别?
- 抽象类可包含抽象方法,普通类不能。
- 抽象类不能直接实例化,普通类可以。
13. 抽象类能使用 final 修饰吗?
不能。final 表示不可继承,abstract 表示需被继承,两者矛盾。
14. 接口和抽象类有什么区别?
- 实现方式:抽象类用 extends,接口用 implements。
- 构造函数:抽象类可以有,接口不能有。
- 数量限制:类可实现多个接口,但只能继承一个抽象类。
- 访问修饰符:接口方法默认为 public,抽象类方法任意。
15. Java 中 IO 流分为几种?
按功能分:输入流(input)、输出流(output)。
按类型分:字节流(8 位)、字符流(16 位)。
16. BIO、NIO、AIO 有什么区别?
- BIO:Block IO,同步阻塞式,传统 IO,并发能力低。
- NIO:Non-blocking IO,同步非阻塞,基于 Channel 多路复用。
- AIO:Asynchronous IO,异步非阻塞,基于事件和回调机制。
17. Files 的常用方法都有哪些?
- exists():检测文件是否存在。
- createFile()/createDirectory():创建文件/目录。
- delete():删除。
- copy()/move():复制/移动。
- read()/write():读写。
容器
18. Java 容器都有哪些?
主要分为 Collection 和 Map 两大类。
- Collection:List (ArrayList, LinkedList, Vector, Stack)、Set (HashSet, LinkedHashSet, TreeSet)。
- Map:HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap, Hashtable。
19. Collection 和 Collections 有什么区别?
- Collection:集合接口,所有集合类的父接口。
- Collections:包装类,提供静态方法(如排序),不能被实例化。
20. List、Set、Map 之间的区别是什么?
- List:有序,允许重复。
- Set:无序(HashSet),不允许重复。
- Map:键唯一,值可重复。
21. HashMap 和 Hashtable 有什么区别?
- Null 值:HashMap 允许 key/value 为 null,Hashtable 不允许。
- 线程安全:Hashtable 线程安全,HashMap 非线程安全。
- 推荐:单线程用 HashMap,多线程用 ConcurrentHashMap。
22. 如何决定使用 HashMap 还是 TreeMap?
插入、删除、定位选 HashMap(更快);需要对 key 有序遍历选 TreeMap。
23. 说一下 HashMap 的实现原理?
基于 Hash 算法。put(key, value) 时计算 hash 值存入 bucket。hash 冲突时用链表或红黑树存储。冲突少用链表,多用红黑树。
24. 说一下 HashSet 的实现原理?
底层基于 HashMap。HashSet 不允许重复值,相关操作直接调用 HashMap 方法。
25. ArrayList 和 LinkedList 的区别是什么?
- 数据结构:ArrayList 是动态数组,LinkedList 是双向链表。
- 随机访问:ArrayList 效率高,LinkedList 需遍历。
- 增删效率:非首尾操作,LinkedList 优于 ArrayList。
频繁读取用 ArrayList,频繁增删用 LinkedList。
26. 如何实现数组和 List 之间的转换?
- 数组转 List:
Arrays.asList(array)。
- List 转数组:
list.toArray()。
27. ArrayList 和 Vector 的区别是什么?
- 线程安全:Vector 线程安全(synchronized),ArrayList 非线程安全。
- 扩容:Vector 扩容 1 倍,ArrayList 扩容 50%。
- 性能:ArrayList 更优。
28. Array 和 ArrayList 有何区别?
- 类型:Array 存基本类型和对象,ArrayList 仅存对象。
- 大小:Array 固定,ArrayList 自动扩展。
- 方法:ArrayList 内置方法更多(addAll, removeAll 等)。
29. 在 Queue 中 poll() 和 remove() 有什么区别?
- 相同点:都返回并删除第一个元素。
- 不同点:空队列时,poll() 返回 null,remove() 抛异常。
30. 哪些集合类是线程安全的?
Vector、Hashtable、Stack 是线程安全的。JDK 1.5+ 后,ConcurrentHashMap 替代了 Hashtable。
31. 迭代器 Iterator 是什么?
提供遍历 Collection 的接口。取代 Enumeration,支持移除元素。
32. Iterator 怎么使用?有什么特点?
List<String> list = new ArrayList<>();
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String obj = it.next();
System.out.println(obj);
}
特点是更安全,遍历时修改集合会抛出 ConcurrentModificationException。
33. Iterator 和 ListIterator 有什么区别?
- 范围:Iterator 遍历 Set/List,ListIterator 仅遍历 List。
- 方向:Iterator 单向,ListIterator 双向。
- 功能:ListIterator 支持添加、替换、获取索引。
34. 怎么确保一个集合不能被修改?
使用 Collections.unmodifiableCollection(Collection c) 创建只读集合。
多线程
35. 并行和并发有什么区别?
- 并行:多核处理器同时处理多个任务。
- 并发:单核 CPU 通过时间片轮流执行多个任务,逻辑上同时。
36. 线程和进程的区别?
进程是资源分配单位,线程是 CPU 调度单位。一个进程至少有一个线程,可包含多个线程。
37. 守护线程是什么?
运行在后台的特殊进程,独立于控制终端。例如垃圾回收线程。
38. 创建线程有哪几种方式?
- 继承 Thread 重写 run 方法。
- 实现 Runnable 接口。
- 实现 Callable 接口。
39. 说一下 runnable 和 callable 有什么区别?
Runnable 无返回值,Callable 有返回值且可抛出异常。
40. 线程有哪些状态?
NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。
41. sleep() 和 wait() 有什么区别?
- 来源:sleep 来自 Thread,wait 来自 Object。
- 锁:sleep 不释放锁,wait 释放锁。
- 唤醒:sleep 时间到自动恢复,wait 需 notify/notifyAll。
42. notify() 和 notifyAll() 有什么区别?
notify() 唤醒一个线程,notifyAll() 唤醒所有线程。
43. 线程的 run() 和 start() 有什么区别?
start() 启动线程,run() 执行代码。run() 可重复调用,start() 只能一次。
44. 创建线程池有哪几种方式?
最核心的是 ThreadPoolExecutor。常见工厂方法包括:
- newSingleThreadExecutor()
- newCachedThreadPool()
- newFixedThreadPool(int nThreads)
- newScheduledThreadPool()
- newWorkStealingPool()
45. 线程池都有哪些状态?
RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED。
46. 线程池中 submit() 和 execute() 方法有什么区别?
execute() 仅执行 Runnable,submit() 可执行 Runnable 和 Callable(可获返回值)。
47. 在 Java 程序中怎么保证多线程的运行安全?
- 使用安全类(java.util.concurrent)。
- 使用 synchronized。
- 使用 Lock(如 ReentrantLock)。
48. 多线程中 synchronized 锁升级的原理是什么?
Java 6 后优化了 synchronized。锁升级路径:偏向锁 -> 轻量级锁 -> 重量级锁。目的是降低锁带来的性能消耗。
49. 什么是死锁?
线程 A 持有锁 a 等待锁 b,线程 B 持有锁 b 等待锁 a,互相阻塞。
50. 怎么防止死锁?
- 设置超时时间(tryLock)。
- 使用并发包代替手写锁。
- 降低锁粒度。
- 减少同步代码块。
51. ThreadLocal 是什么?有哪些使用场景?
为每个线程提供独立变量副本。典型场景:数据库连接管理、Session 管理。
52. 说一下 synchronized 底层实现原理?
由 monitorenter/monitorexit 指令实现。Java 6 前依赖操作系统互斥锁(重量级),6 后引入偏向锁、轻量级锁、重量级锁三种 monitor 实现。
53. synchronized 和 volatile 的区别是什么?
- 作用:volatile 修饰变量,synchronized 修饰类/方法/块。
- 原子性:volatile 不保证原子性,synchronized 保证。
- 阻塞:volatile 不阻塞,synchronized 可能阻塞。
54. synchronized 和 Lock 有什么区别?
- 范围:synchronized 可修饰类/方法/块,Lock 仅代码块。
- 释放:synchronized 自动释放,Lock 需手动 unlock。
- 查询:Lock 可判断是否获取成功,synchronized 不行。
55. synchronized 和 ReentrantLock 区别是什么?
ReentrantLock 更灵活但需手动释放;synchronized 简单且异常时自动释放。Java 6 后 synchronized 性能已大幅提升。
56. 说一下 atomic 的原理?
利用 CAS (Compare And Swap) 和 volatile 及 native 方法保证原子操作,避免 synchronized 高开销。
反射
57. 什么是反射?
运行时动态获取类的所有属性和方法,并动态调用对象的方法和功能。
58. 什么是 Java 序列化?什么情况下需要序列化?
保存对象状态到文件或数据库,或通过网络传输。场景:RMI、套接字传输、持久化。
59. 动态代理是什么?有哪些应用?
运行时动态生成代理类。应用:Spring AOP、Hibernate 数据查询、RPC。
60. 怎么实现动态代理?
JDK 原生动态代理(基于接口)和 CGLIB(基于继承子类)。
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online