跳到主要内容
Java 面试核心知识点与常见问答整理 | 极客日志
Java java
Java 面试核心知识点与常见问答整理 Java 面试涵盖基础语法、集合框架、并发编程、Web 技术及中间件等核心领域。内容涉及 JDK 与 JRE 区别、equals 与 hashCode 原理、String 不可变性、HashMap 实现机制、线程池状态及锁升级过程等高频考点。通过梳理这些关键问题与代码示例,帮助开发者巩固理论基础,应对实际面试挑战。
FrontendX 发布于 2026/3/15 更新于 2026/4/29 3 浏览Java 基础
1. JDK 和 JRE 有什么区别?
JDK :Java Development Kit 的简称,即 Java 开发工具包,提供了 Java 的开发环境和运行环境。
JRE :Java Runtime Environment 的简称,即 Java 运行环境,为 Java 的运行提供了所需环境。
具体来说,JDK 其实包含了 JRE,同时还包含了编译 Java 源码的编译器 javac,以及很多 Java 程序调试和分析的工具。简单来说:如果你只需要运行 Java 程序,安装 JRE 就够了;如果需要编写 Java 程序,则必须安装 JDK。
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 比较的是值,所以结果都为 true。
「equals 解读」
equals 本质上就是 ==,只不过 String、Integer 等类重写了该方法,将其变成了值比较。
默认情况下,equals 比较一个有相同值的对象,代码如下:
class Cat {
public Cat {
.name = name;
}
String name;
String { name; }
{ .name = name; }
}
( );
( );
System.out.println(c1.equals(c2));
(String name)
this
private
public
getName
()
return
public
void
setName
(String name)
this
Cat
c1
=
new
Cat
"王磊"
Cat
c2
=
new
Cat
"王磊"
输出结果出乎意料,竟然是 false?查看 Object 类的源码就知道了:
public boolean equals (Object obj) {
return (this == obj);
}
原来 equals 默认就是引用比较。那为什么两个相同值的 String 对象返回 true?这是因为 String 重写了 Object 的 equals 方法,将引用比较改成了值比较。
「总结」 :== 对基本类型是值比较,对引用类型是比较引用;equals 默认是引用比较,但许多类(如 String、Integer)重写了它变成值比较,所以一般情况下 equals 比较的是值是否相等。
3. 两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗? 不对。两个对象的 hashCode() 相同,equals() 不一定为 true。
String str1 = "通话" ;
String str2 = "重地" ;
System.out.println(String.format("str1:%d | str2:%d" , str1.hashCode(), str2.hashCode()));
System.out.println(str1.equals(str2));
str1: 1179395 | str2:1179395 false
代码解读:显然'通话'和'重地'的 hashCode() 相同,但 equals() 为 false。因为在散列表中,hashCode() 相等仅表示哈希值相等,并不一定能得出键值对相等,这就是哈希冲突现象。
4. final 在 Java 中有什么作用?
final 修饰的类叫最终类,该类不能被继承。
final 修饰的方法不能被重写。
final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
5. Java 中的 Math.round(-1.5) 等于多少? 等于 -1。因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 往上取整,负 0.5 直接舍弃。
6. String 属于基础的数据类型吗? 不属于。基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。
7. Java 中操作字符串都有哪些类?它们之间有什么区别? 操作字符串的类主要有:String、StringBuffer、StringBuilder。
String :声明的是不可变对象,每次操作都会生成新的 String 对象,指针指向新对象。经常改变字符串内容时不建议使用。
StringBuffer / StringBuilder :可以在原有对象基础上进行操作,性能更高。
区别 :StringBuffer 是线程安全的,StringBuilder 是非线程安全,但 StringBuilder 性能高于 StringBuffer。单线程推荐 StringBuilder,多线程推荐 StringBuffer。
8. String str="i"与 String str=new String('i')一样吗?
String str="i":Java 虚拟机会将其分配到常量池中。
String str=new String('i'):会被分到堆内存中。
9. 如何将字符串反转? 使用 StringBuilder 或 StringBuffer 的 reverse() 方法。
StringBuffer stringBuffer = new StringBuffer ();
stringBuffer.append("abcdefg" );
System.out.println(stringBuffer.reverse());
StringBuilder stringBuilder = new StringBuilder ();
stringBuilder.append("abcdefg" );
System.out.println(stringBuilder.reverse());
10. String 类的常用方法都有那些?
indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回数组。
getBytes():返回 byte 类型数组。
length():返回长度。
toLowerCase() / toUpperCase():大小写转换。
substring():截取字符串。
equals():字符串比较。
11. 抽象类必须要有抽象方法吗? abstract class Cat {
public static void sayHi () {
System.out.println("hi~" );
}
}
12. 普通类和抽象类有哪些区别?
普通类不能包含抽象方法,抽象类可以。
抽象类不能直接实例化,普通类可以直接实例化。
13. 抽象类能使用 final 修饰吗? 不能。定义抽象类是为了让其他类继承,如果定义为 final 则不能被继承,两者矛盾,编辑器也会报错。
14. 接口和抽象类有什么区别?
实现 :抽象类子类用 extends 继承;接口用 implements 实现。
构造函数 :抽象类可以有;接口不能有。
数量 :类可以实现多个接口,但只能继承一个抽象类。
修饰符 :接口方法默认 public;抽象类方法可以是任意访问修饰符。
15. Java 中 IO 流分为几种?
按功能 :输入流(input)、输出流(output)。
按类型 :字节流和字符流。
区别 :字节流按 8 位传输(以字节为单位),字符流按 16 位传输(以字符为单位)。
16. BIO、NIO、AIO 有什么区别?
BIO :Block IO,同步阻塞式 IO。模式简单,并发处理能力低。
NIO :Non Blocking IO,同步非阻塞 IO。通过 Channel 通讯,实现了多路复用。
AIO :Asynchronous IO,异步非阻塞 IO。基于事件和回调机制。
17. Files 的常用方法都有哪些?
Files.exists():检测文件路径是否存在。
Files.createFile():创建文件。
Files.createDirectory():创建文件夹。
Files.delete():删除文件或目录。
Files.copy():复制文件。
Files.move():移动文件。
Files.size():查看文件大小。
Files.read() / Files.write():读写文件。
容器
18. Java 容器都有哪些? Java 容器分为 Collection 和 Map 两大类:
Collection
List:ArrayList, LinkedList, Vector, Stack
Set:HashSet, LinkedHashSet, TreeSet
Map
HashMap, LinkedHashMap, TreeMap
ConcurrentHashMap, Hashtable
19. Collection 和 Collections 有什么区别?
Collection :集合接口,提供对集合对象进行基本操作的通用接口方法,所有集合都是它的子类。
Collections :包装类,包含很多静态方法,不能被实例化,类似工具类(如 Collections.sort(list))。
20. List、Set、Map 之间的区别是什么?
21. HashMap 和 Hashtable 有什么区别?
存储 :HashMap 允许 key 和 value 为 null,Hashtable 不允许。
线程安全 :Hashtable 是线程安全的,HashMap 是非线程安全的。
推荐使用 :Hashtable 是遗留类,建议单线程用 HashMap,多线程用 ConcurrentHashMap。
22. 如何决定使用 HashMap 还是 TreeMap?
插入、删除、定位操作频繁:选 HashMap,效率更高。
需要对 key 集合进行有序遍历:选 TreeMap。
23. 说一下 HashMap 的实现原理? 基于 Hash 算法。通过 put(key, value) 存储,get(key) 获取。传入 key 时,根据 key.hashCode() 计算 hash 值,将 value 保存在 bucket 里。hash 值相同时称为 hash 冲突,HashMap 用链表和红黑树存储。冲突少时用链表,多时转红黑树。
24. 说一下 HashSet 的实现原理? 基于 HashMap 实现。底层使用 HashMap 保存所有元素,操作直接调用底层 HashMap 方法,不允许重复值。
25. ArrayList 和 LinkedList 的区别是什么?
数据结构 :ArrayList 是动态数组,LinkedList 是双向链表。
随机访问 :ArrayList 效率高,LinkedList 需移动指针查找。
增删效率 :非首尾增删,LinkedList 效率更高,ArrayList 会影响下标。
综合来说,频繁读取推荐 ArrayList,频繁增删推荐 LinkedList。
26. 如何实现数组和 List 之间的转换?
数组转 List :Arrays.asList(array)。
List 转数组 :list.toArray()。
List<String> list = new ArrayList <>();
list.add("王磊" );
list.toArray();
String[] array = {"王磊" , "的博客" };
Arrays.asList(array);
27. ArrayList 和 Vector 的区别是什么?
线程安全 :Vector 使用 synchronized 实现线程同步,是线程安全的;ArrayList 非线程安全。
性能 :ArrayList 优于 Vector。
扩容 :Vector 扩容增加 1 倍,ArrayList 增加 50%。
28. Array 和 ArrayList 有何区别?
类型 :Array 可存基本类型和对象,ArrayList 只能存对象。
大小 :Array 固定大小,ArrayList 自动扩展。
方法 :Array 内置方法少,ArrayList 有更多工具方法(如 addAll, removeAll)。
29. 在 Queue 中 poll() 和 remove() 有什么区别?
相同点 :都返回第一个元素并删除。
不同点 :空队列时,poll() 返回 null,remove() 抛出 NoSuchElementException 异常。
30. 哪些集合类是线程安全的? Vector、Hashtable、Stack 是线程安全的。JDK 1.5 后 java.util.concurrent 包提供了更多选择,如 ConcurrentHashMap。
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) 创建只读集合,修改操作会抛出 UnsupportedOperationException。
List<String> list = new ArrayList <>();
list.add("x" );
Collection<String> clist = Collections.unmodifiableCollection(list);
clist.add("y" );
多线程
35. 并行和并发有什么区别?
并行 :多个处理器或多核同时处理多个任务。
并发 :同一 CPU 核按时间片轮流执行多个任务,逻辑上看似同时。
36. 线程和进程的区别? 一个程序至少有一个进程,一个进程至少有一个线程。多线程可增加程序执行速度。
37. 守护线程是什么? 运行在后台的特殊进程,独立于控制终端,周期性执行任务或等待事件。垃圾回收线程就是特殊的守护线程。
38. 创建线程有哪几种方式?
继承 Thread 重写 run 方法。
实现 Runnable 接口。
实现 Callable 接口。
39. 说一下 runnable 和 callable 有什么区别? Runnable 无返回值,Callable 有返回值,可看作是 Runnable 的补充。
40. 线程有哪些状态?
NEW :尚未启动。
RUNNABLE :正在执行中。
BLOCKED :阻塞(被锁或 IO 阻塞)。
WAITING :永久等待。
TIMED_WAITING :等待指定时间。
TERMINATED :执行完成。
41. sleep() 和 wait() 有什么区别?
类来源 :sleep() 来自 Thread,wait() 来自 Object。
释放锁 :sleep() 不释放锁;wait() 释放锁。
用法 :sleep() 时间到自动恢复;wait() 可用 notify()/notifyAll() 唤醒。
42. notify() 和 notifyAll() 有什么区别? notifyAll() 唤醒所有线程,将它们由等待池移到锁池参与竞争;notify() 只唤醒一个线程,具体由虚拟机控制。
43. 线程的 run() 和 start() 有什么区别? start() 用于启动线程;run() 用于执行代码。run() 可重复调用,start() 只能调用一次。
44. 创建线程池有哪几种方式? 最核心的是最后一种 ThreadPoolExecutor,其他方式多为封装:
newSingleThreadExecutor():单线程,顺序执行。
newCachedThreadPool():缓存线程,大量短时间任务。
newFixedThreadPool(int nThreads):固定线程数。
newSingleThreadScheduledExecutor():单线程定时调度。
newScheduledThreadPool(int corePoolSize):多线程定时调度。
newWorkStealingPool(int parallelism):Java 8 加入,利用 Work-Stealing 算法并行处理。
ThreadPoolExecutor():最原始创建方式。
45. 线程池都有哪些状态?
RUNNING :接受新任务,处理等待队列。
SHUTDOWN :不接受新任务,继续处理等待队列。
STOP :不接受新任务,不再处理等待队列,中断正在执行的任务。
TIDYING :所有任务销毁,workCount 为 0,执行钩子方法 terminated()。
TERMINATED :terminated() 结束后进入此状态。
46. 线程池中 submit() 和 execute() 方法有什么区别?
execute() :只能执行 Runnable 类型任务。
submit() :可执行 Runnable 和 Callable 类型任务,后者可获取返回值。
47. 在 Java 程序中怎么保证多线程的运行安全?
使用安全类(如 java.util.concurrent 下的类)。
使用自动锁 synchronized。
使用手动锁 Lock。
Lock lock = new ReentrantLock ();
lock.lock();
try {
System.out.println("获得锁" );
} catch (Exception e) {
} finally {
System.out.println("释放锁" );
lock.unlock();
}
48. 多线程中 synchronized 锁升级的原理是什么? 锁升级目的是降低性能消耗。Java 6 后优化了 synchronized 实现:
偏向锁 :首次访问,threadid 为空,设置为其线程 ID。
轻量级锁 :若 threadid 不一致,自旋循环尝试获取锁。
重量级锁 :自旋失败后升级为重量级锁,依赖操作系统互斥锁。
49. 什么是死锁? 线程 A 持有锁 a 尝试获取锁 b,线程 B 持有锁 b 尝试获取锁 a,互相阻塞的现象。
50. 怎么防止死锁?
使用 tryLock(long timeout, TimeUnit unit) 设置超时时间。
尽量使用 java.util.concurrent 并发类代替手写锁。
降低锁粒度,减少同步代码块。
51. ThreadLocal 是什么?有哪些使用场景? 为每个使用该变量的线程提供独立副本,互不影响。经典场景:数据库连接、Session 管理等。
52. 说一下 synchronized 底层实现原理? 由一对 monitorenter/monitorexit 指令实现。Java 6 前完全依靠操作系统互斥锁(重量级)。Java 6 后引入三种 monitor 实现:偏向锁、轻量级锁、重量级锁,大幅改进性能。
53. synchronized 和 volatile 的区别是什么?
修饰 :volatile 修饰变量;synchronized 修饰类、方法、代码段。
原子性 :volatile 仅保证可见性,不保证原子性;synchronized 两者都保证。
阻塞 :volatile 不会造成阻塞;synchronized 可能阻塞。
54. synchronized 和 Lock 有什么区别?
范围 :synchronized 可给类、方法、代码块加锁;Lock 只能给代码块加锁。
释放 :synchronized 自动释放,异常也会释放;Lock 需手动 unlock(),否则易死锁。
判断 :Lock 可判断是否成功获取锁,synchronized 无法办到。
55. synchronized 和 ReentrantLock 区别是什么? Java 6 后 synchronized 性能已大幅提升。主要区别:
ReentrantLock 更灵活,但必须配合释放锁动作。
ReentrantLock 需手动获取与释放;synchronized 无需。
ReentrantLock 仅适用于代码块;synchronized 可用于方法和代码块。
56. 说一下 atomic 的原理? 主要利用 CAS (Compare And Swap)、volatile 和 native 方法保证原子操作,避免 synchronized 高开销,提升执行效率。
反射
57. 什么是反射? 在运行状态中,对于任意一个类,都能知道其所有属性和方法;对于任意一个对象,都能调用其任意方法和属性。这种动态获取信息及调用的功能称为反射机制。
58. 什么是 Java 序列化?什么情况下需要序列化? 为了保存对象在内存中的状态,并可再读出来。以下情况需要:
保存对象状态到文件或数据库。
通过网络套接字传送对象。
通过 RMI 传输对象。
59. 动态代理是什么?有哪些应用? 运行时动态生成代理类。应用包括 Spring AOP、Hibernate 数据查询、测试框架 Mock、RPC、注解对象获取等。
60. 怎么实现动态代理?
JDK 原生动态代理 :基于接口实现。
CGLIB 动态代理 :基于继承当前类的子类实现。
对象拷贝
61. 为什么要使用克隆? 克隆的对象可能包含已修改的属性,而 new 出来的对象属性仍是初始值。当需要新对象保存当前对象'状态'时,靠克隆方法。
62. 如何实现对象克隆?
实现 Cloneable 接口并重写 Object.clone() 方法。
实现 Serializable 接口,通过序列化和反序列化实现真正的深度克隆。
63. 深拷贝和浅拷贝区别是什么?
浅拷贝 :复制对象本身及值类型成员变量,引用类型成员对象未复制。
深拷贝 :除对象本身外,所有成员变量均复制。
Java Web
64. JSP 和 servlet 有什么区别? JSP 是 Servlet 技术的扩展,本质上是 Servlet 的简易方式。
Servlet :应用逻辑在 Java 文件中,从 HTML 分离,侧重控制逻辑。
JSP :Java 和 HTML 组合成 .jsp 文件,侧重视图。
65. JSP 有哪些内置对象?作用分别是什么?
request :封装客户端请求参数。
response :封装服务器响应。
pageContext :获取其他对象。
session :封装用户会话。
application :封装服务器运行环境。
out :输出流对象。
config :Web 应用配置对象。
page :JSP 页面本身(相当于 this)。
exception :封装页面异常对象。
66. 说一下 JSP 的 4 种作用域?
page :与一个页面相关。
request :与一个请求相关,跨页面临时数据。
session :与用户会话相关,用户私有数据。
application :与整个 Web 应用相关,全局作用域。
67. session 和 cookie 有什么区别?
存储位置 :session 在服务端;cookie 在浏览器端。
安全性 :cookie 一般,可被伪造修改;session 相对更安全。
容量限制 :cookie 有容量和个数限制;session 取决于服务端资源。
多样性 :session 可存在 Redis、DB 或应用中;cookie 只能在浏览器。
相关免费在线工具 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