跳到主要内容Java 核心面试题与解析 | 极客日志Javajava
Java 核心面试题与解析
整理 Java 开发核心面试题,涵盖基础语法、集合框架、多线程并发、反射机制及 Web 技术栈。内容涉及 JDK 与 JRE 区别、equals 与 hashCode 规范、HashMap 原理、线程池状态管理、锁升级机制等高频考点。旨在帮助开发者梳理知识体系,应对技术面试挑战。
蜜桃汽水1 浏览 本文整理了 Java 开发中常见的核心面试题,涵盖基础、容器、多线程等模块,旨在帮助开发者梳理知识体系。
Java 基础
1. JDK 和 JRE 有什么区别?
- JDK:Java Development Kit,开发工具包,提供开发环境和运行环境。
- JRE:Java Runtime Environment,运行环境,为 Java 程序运行提供支持。
简单来说,JDK 包含了 JRE,还多了编译器和调试分析工具。如果只需运行程序,安装 JRE 即可;若要编写代码,则必须安装 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 默认比较引用,但 String 类重写了该方法进行值比较。
equals 的本质
Object 类的 equals 本质上就是 ==。String 和 Integer 等类重写了它,将其变为值比较。
class Cat {
public Cat(String name) { this.name = name; }
private String name;
public String getName() { return name; }
}
Cat c1 = ();
();
System.out.println(c1.equals(c2));
new
Cat
"王磊"
Cat
c2
=
new
Cat
"王磊"
自定义类未重写 equals 时,即使内容相同,比较结果也是 false。String 源码中通过逐字符比较实现了值相等判断。
3. 两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?
不对。hashCode 相同只意味着哈希值相等,可能存在哈希冲突,此时 equals() 不一定为 true。
String str1 = "通话";
String str2 = "重地";
System.out.println(str1.hashCode() + " | " + str2.hashCode());
System.out.println(str1.equals(str2));
执行结果显示两者 hash 值相同但 equals 返回 false,这符合散列表的设计逻辑。
4. final 在 Java 中有什么作用?
- 修饰类:该类不能被继承。
- 修饰方法:该方法不能被重写。
- 修饰变量:成为常量,初始化后不可修改。
5. Java 中的 Math.round(-1.5) 等于多少?
等于 -1。round 方法是向最接近的整数取整,0.5 向右取整,负数同理。
6. String 属于基础的数据类型吗?
不属于。基础类型有 8 种(byte, boolean, char, short, int, float, long, double),String 是对象。
7. Java 中操作字符串都有哪些类?它们之间有什么区别?
主要有 String、StringBuffer、StringBuilder。
- String:不可变对象,每次修改都会生成新对象。
- StringBuffer:可变,线程安全,性能略低。
- StringBuilder:可变,非线程安全,性能更高。
单线程下推荐 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(), length(), toLowerCase(), toUpperCase(), substring(), equals() 等。
11. 抽象类必须要有抽象方法吗?
不需要。抽象类可以没有抽象方法,但不能直接实例化。
12. 普通类和抽象类有哪些区别?
- 普通类不能包含抽象方法,可直接实例化。
- 抽象类可包含抽象方法,不可直接实例化。
13. 抽象类能使用 final 修饰吗?
不能。final 禁止继承,abstract 要求被继承,二者矛盾。
14. 接口和抽象类有什么区别?
- 实现方式:抽象类用 extends,接口用 implements。
- 构造函数:抽象类可以有,接口不能有。
- 继承数量:类可实现多个接口,但只能继承一个抽象类。
- 访问修饰符:接口方法默认为 public,抽象类方法任意。
15. Java 中 IO 流分为几种?
按功能分输入流和输出流;按类型分字节流和字符流。字节流按 8 位传输,字符流按 16 位传输。
16. BIO、NIO、AIO 有什么区别?
- BIO:同步阻塞 IO,模式简单,并发能力低。
- NIO:同步非阻塞 IO,基于 Channel 和多路复用。
- AIO:异步非阻塞 IO,基于事件和回调机制。
17. Files 的常用方法有哪些?
exists(), createFile(), createDirectory(), delete(), copy(), move(), size(), read(), write() 等。
容器
18. Java 容器都有哪些?
主要分为 Collection 和 Map 两大类。Collection 下有 List(ArrayList, LinkedList 等)和 Set(HashSet, TreeSet 等)。Map 下有 HashMap, TreeMap 等。
19. Collection 和 Collections 有什么区别?
- Collection:集合接口,List、Set 等的父接口。
- Collections:包装类,提供静态方法(如排序),不可实例化。
20. List、Set、Map 之间的区别是什么?
主要区别在于元素是否有序、是否允许重复。List 有序且可重复,Set 无序且不可重复,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) 时计算 key 的 hashCode 确定 bucket 位置。若 hash 冲突,使用链表或红黑树存储。冲突少时用链表,多时转红黑树。
24. 说一下 HashSet 的实现原理?
基于 HashMap 实现。底层用 HashMap 保存元素,key 即为元素本身,value 为固定对象。不允许重复值。
25. ArrayList 和 LinkedList 的区别是什么?
- 结构:ArrayList 是动态数组,LinkedList 是双向链表。
- 随机访问:ArrayList 效率高,LinkedList 需遍历。
- 增删效率:非首尾操作 LinkedList 更优,ArrayList 涉及数组移动。
频繁读取选 ArrayList,频繁增删选 LinkedList。
26. 如何实现数组和 List 之间的转换?
- 数组转 List:Arrays.asList(array)
- List 转数组:list.toArray()
String[] array = {"a", "b"};
List<String> list = Arrays.asList(array);
27. ArrayList 和 Vector 的区别是什么?
- 线程安全:Vector 线程安全(synchronized),ArrayList 非线程安全。
- 扩容:Vector 扩容 1 倍,ArrayList 扩容 50%。
- 性能:ArrayList 优于 Vector。
28. Array 和 ArrayList 有何区别?
- Array 可存基本类型和对象,ArrayList 仅存对象。
- Array 大小固定,ArrayList 自动扩展。
- ArrayList 内置方法更多。
29. 在 Queue 中 poll() 和 remove() 有什么区别?
- 都返回并删除第一个元素。
- 队列为空时,poll() 返回 null,remove() 抛出异常。
30. 哪些集合类是线程安全的?
Vector、Hashtable、Stack 是线程安全的。JDK 1.5 后推荐使用 java.util.concurrent 包下的类,如 ConcurrentHashMap。
31. 迭代器 Iterator 是什么?
提供遍历 Collection 的接口,取代了 Enumeration,支持在迭代过程中移除元素。
32. Iterator 怎么使用?有什么特点?
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String obj = it.next();
}
特点:更安全,遍历时集合被修改会抛出 ConcurrentModificationException。
33. Iterator 和 ListIterator 有什么区别?
- 范围:Iterator 遍历 Set/List,ListIterator 仅遍历 List。
- 方向:Iterator 单向,ListIterator 双向。
- 功能:ListIterator 支持添加、替换元素及获取索引。
34. 怎么确保一个集合不能被修改?
使用 Collections.unmodifiableCollection() 创建只读集合,修改操作将抛出 UnsupportedOperationException。
多线程
35. 并行和并发有什么区别?
- 并行:多核处理器同时处理多个任务。
- 并发:单核 CPU 通过时间片轮流执行多个任务,逻辑上同时。
36. 线程和进程的区别?
进程是资源分配单位,线程是 CPU 调度单位。一个进程至少有一个线程。
37. 守护线程是什么?
运行在后台的特殊进程,独立于控制终端。例如垃圾回收线程。
38. 创建线程有哪几种方式?
- 继承 Thread 重写 run 方法。
- 实现 Runnable 接口。
- 实现 Callable 接口。
39. 说一下 runnable 和 callable 有什么区别?
Runnable 无返回值,Callable 可返回结果。Callable 可视为 Runnable 的补充。
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() 唤醒所有线程。notifyAll 将所有等待线程移入锁池参与竞争。
43. 线程的 run() 和 start() 有什么区别?
start() 启动线程,run() 执行代码。start() 只能调用一次,run() 可重复调用。
44. 创建线程池有哪几种方式?
常见方式包括 newSingleThreadExecutor, newCachedThreadPool, newFixedThreadPool 等。最核心的是 ThreadPoolExecutor,其他多为封装。
45. 线程池都有哪些状态?
RUNNING(接受任务)、SHUTDOWN(不接受新任务)、STOP(中断任务)、TIDYING(任务销毁)、TERMINATED(终止)。
46. 线程池中 submit() 和 execute() 方法有什么区别?
execute() 仅执行 Runnable,submit() 可执行 Runnable 和 Callable(可获取返回值)。
47. 在 Java 程序中怎么保证多线程的运行安全?
- 使用安全类(java.util.concurrent)。
- 使用 synchronized 锁。
- 使用 Lock 手动锁。
Lock lock = new ReentrantLock();
lock.lock();
try { } finally { lock.unlock(); }
48. 多线程中 synchronized 锁升级的原理是什么?
Java 6 优化了 synchronized,引入偏向锁、轻量级锁、重量级锁。初始为偏向锁,竞争时升级为轻量级锁(自旋),再升级为重量级锁。目的是减少锁带来的性能消耗。
49. 什么是死锁?
线程 A 持有锁 a 等待锁 b,线程 B 持有锁 b 等待锁 a,互相阻塞无法继续。
50. 怎么防止死锁?
- 使用 tryLock 设置超时。
- 尽量使用并发包类代替手写锁。
- 降低锁粒度,减少同步块。
51. ThreadLocal 是什么?有哪些使用场景?
为每个线程提供独立变量副本,互不影响。常用于数据库连接、Session 管理等。
52. 说一下 synchronized 底层实现原理?
基于 monitorenter/monitorexit 指令。Java 6 前依赖操作系统互斥锁(重量级),Java 6 后引入三种锁优化性能。
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 保证原子操作,避免 synchronized 高开销。
反射
57. 什么是反射?
运行时动态获取类的所有属性和方法,并动态调用对象的方法。这是 Java 语言的重要特性。
58. 什么是 Java 序列化?什么情况下需要序列化?
将对象状态保存到文件或数据库,或通过网络传输。适用于 RMI、网络套接字传输等场景。
59. 动态代理是什么?有哪些应用?
运行时动态生成代理类。应用包括 Spring AOP、Hibernate 查询、RPC 等。
60. 怎么实现动态代理?
JDK 原生代理基于接口,CGLIB 基于继承子类。
对象拷贝
61. 为什么要使用克隆?
当需要保存当前对象状态并生成新对象时使用,避免新对象属性仅为初始值。
62. 如何实现对象克隆?
- 实现 Cloneable 接口并重写 clone()。
- 实现 Serializable 接口,通过序列化和反序列化实现深度克隆。
63. 深拷贝和浅拷贝区别是什么?
- 浅拷贝:复制对象本身及值类型成员,引用类型成员不复制。
- 深拷贝:复制对象及其所有成员变量(包括引用指向的对象)。
Java Web
64. JSP 和 servlet 有什么区别?
JSP 是 Servlet 的简化形式,侧重视图;Servlet 侧重控制逻辑。JSP 本质是 Servlet。
65. JSP 有哪些内置对象?
request, response, pageContext, session, application, out, config, page, exception。共 9 个。
66. 说一下 JSP 的 4 种作用域?
- page:页面相关。
- request:请求相关。
- session:会话相关。
- application:全局应用相关。
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