跳到主要内容Java 基础面试高频问题深度解析 | 极客日志Javajava算法
Java 基础面试高频问题深度解析
Java 基础面试涵盖 JDK 与 JRE 区别、集合框架原理、多线程并发机制、反射与序列化、异常处理及网络协议等关键领域。内容针对 HashMap 底层实现、锁升级过程、线程状态转换等难点进行了详细拆解,适合希望系统复习 Java 基础并应对技术面试的开发者参考。
一、Java 基础
1. JDK 和 JRE 有什么区别?
JDK(Java Development Kit)是 Java 开发工具包,包含了 JRE 以及编译器、调试器等开发工具。JRE(Java Runtime Environment)是 Java 运行时环境,仅包含运行 Java 程序所需的类库和虚拟机。
简单来说:JDK = JRE + 开发工具。开发者需要安装 JDK,而普通用户只需安装 JRE。
2. == 和 equals 的区别是什么?
- ==:运算符。对于基本数据类型比较值;对于引用类型比较内存地址。
- equals:方法。默认比较引用地址,但通常会被重写以比较对象内容(如 String 类)。
3. 两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?
不对。哈希冲突是常见现象。hashCode() 相同只意味着它们可能存储在哈希表的同一个桶中,仍需通过 equals() 进一步判断是否真正相等。
4. final 在 java 中有什么作用?
- 修饰类:类不能被继承(如 String)。
- 修饰方法:方法不能被子类重写。
- 修饰变量:成为常量,初始化后不可修改。
5. java 中的 Math.round(-1.5) 等于多少?
结果是 -1。Math.round() 采用'四舍五入'策略,负数时向零靠拢(即 -1.5 向上取整为 -1)。
6. String 属于基础的数据类型吗?
不属于。String 是引用类型,是一个类。
7. java 中操作字符串都有哪些类?它们之间有什么区别?
主要涉及 String、StringBuilder、StringBuffer。
- String:不可变,线程安全,频繁修改性能差。
- StringBuilder:可变,非线程安全,单线程下性能最高。
- StringBuffer:可变,线程安全,多线程下使用。
8. String str="i"与 String str=new String("i")一样吗?
不一样。前者直接引用常量池中的对象,后者在堆上新建对象。使用 == 比较结果为 false,equals() 比较结果为 true。
9. 如何将字符串反转?
推荐使用 StringBuilder 或 StringBuffer 的 reverse() 方法。
10. String 类的常用方法都有那些?
包括 length()、charAt()、substring()、indexOf()、trim()、split()、replace()、toLowerCase() 等。注意所有修改操作都会返回新对象。
11. 抽象类必须要有抽象方法吗?
不需要。抽象类可以没有抽象方法,但不能被实例化。
12. 抽象类能使用 final 修饰吗?
不能。abstract 表示可被继承,final 表示不可被继承,两者矛盾。
13. 接口和抽象类有什么区别?
- 继承:类可实现多个接口,只能继承一个抽象类。
- 成员:接口属性默认为 public static final,方法默认为 public abstract(JDK 8+ 可有 default/static 方法)。
- 用途:接口定义行为规范,抽象类提供部分实现。
14. java 中 IO 流分为几种?
按流向分:输入流、输出流。
按类型分:字节流(InputStream/OutputStream)、字符流(Reader/Writer)。
按功能分:节点流(直接操作设备)、处理流(封装其他流)。
15. BIO、NIO、AIO 有什么区别?
- BIO:同步阻塞。一个连接一个线程,适合连接少且固定的场景。
- NIO:同步非阻塞。基于 Channel 和 Selector,支持高并发,适合短连接。
- AIO:异步非阻塞。基于事件和回调,适合长连接场景。
16. Files 的常用方法都有哪些?
位于 java.nio.file.Files 类中,如 createFile()、delete()、readAllBytes()、copy()、move() 等,提供了现代的文件操作 API。
二、容器
17. java 容器都有哪些?
主要分为 List、Set、Map、Queue、Deque 等。常见实现包括 ArrayList、LinkedList、HashSet、HashMap、TreeMap 等。
18. Java 中容器和集合的区别
容器是广义概念,包含数组和集合;集合特指 Java 集合框架(Collection 体系)。日常开发中常混用,但严格来说集合是容器的子集。
19. Collection 和 Collections 有什么区别?
- Collection:接口,List/Set/Queue 的父接口。
- Collections:工具类,提供排序、同步等静态方法。
20. List、Set、Map 之间的区别是什么?
- List:有序,可重复。
- Set:无序(HashSet),不可重复。
- Map:键值对,Key 唯一,Value 可重复。
21. HashMap 和 Hashtable 有什么区别?
- 线程安全:Hashtable 是线程安全的(synchronized),HashMap 不是。
- Null 值:HashMap 允许 null 键值,Hashtable 不允许。
- 性能:HashMap 性能更高。
- 迭代器:Hashtable 支持 Enumeration,HashMap 仅支持 Iterator。
22. 如何决定使用 HashMap 还是 TreeMap?
- HashMap:追求性能,不要求顺序。
- TreeMap:需要按键排序。
23. 说一下 HashMap 的实现原理?
底层是数组 + 链表 + 红黑树(JDK 8+)。当链表长度超过 8 且数组长度大于 64 时,链表转为红黑树以提高查询效率。扩容机制为 2 倍增长。
24. 说一下 HashSet 的实现原理?
HashSet 底层依赖 HashMap。元素作为 Key 存储,Value 为一个固定的 PRESENT 对象。利用 Map 的 Key 唯一性保证 Set 的元素唯一性。
25. ArrayList 和 LinkedList 的区别是什么?
- 底层:ArrayList 是动态数组,LinkedList 是双向链表。
- 访问:ArrayList 随机访问快 O(1),LinkedList 慢 O(n)。
- 增删:ArrayList 中间增删需移动元素,LinkedList 仅需修改指针。
26. 如何实现数组和 List 之间的转换?
- 数组转 List:
Arrays.asList(array)(固定大小)或 new ArrayList<>(list)。
- List 转数组:
list.toArray(new String[0]) 或 Stream API。
27. ArrayList 和 Vector 的区别是什么?
Vector 是线程安全的(方法 synchronized),性能较低;ArrayList 非线程安全,性能更好。建议优先使用 ArrayList,必要时配合 Collections.synchronizedList。
28. Array 和 ArrayList 有何区别?
Array 大小固定,可存基本类型;ArrayList 大小可变,只能存对象,功能更丰富。
29. 在 Queue 中 poll() 和 remove() 有什么区别?
- poll():获取并移除头部元素,队列为空时返回 null。
- remove():获取并移除头部元素,队列为空时抛出异常。
30. 哪些集合类是线程安全的?
Vector、Hashtable、Stack、ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue 等。
31. 迭代器 Iterator 是什么?
一种设计模式,用于遍历集合而不暴露内部结构。提供 hasNext()、next()、remove() 方法。
32. Iterator 怎么使用?有什么特点?
通过 collection.iterator() 获取。特点是统一访问方式、支持安全移除、单向遍历。注意遍历时不要直接修改集合,否则可能触发 ConcurrentModificationException。
33. Iterator 和 ListIterator 有什么区别?
ListIterator 是 Iterator 的子接口,专用于 List。支持双向遍历(previous/next),支持修改元素(set/add)。
34. 怎么确保一个集合不能被修改?
使用 Collections.unmodifiableList() 包装,或使用 Java 9+ 的 List.of() 创建不可变集合。
三、多线程
35. 并行和并发有什么区别?
- 并行:多核同时执行多个任务。
- 并发:单核时间片轮转交替执行,宏观上同时。
36. 线程和进程的区别?
进程是资源分配单位,线程是 CPU 调度单位。线程共享进程资源,切换开销小,通信方便。
37. 守护线程是什么?
服务于其他线程的后台线程。当所有用户线程结束时,守护线程自动终止,不阻止 JVM 退出。
38. 创建线程有哪几种方式?
- 继承 Thread 类。
- 实现 Runnable 接口。
- 实现 Callable 接口 + FutureTask。
- 使用线程池(ExecutorService)。
39. 说一下 runnable 和 callable 有什么区别?
- 返回值:Runnable 无返回值,Callable 有。
- 异常:Runnable 不能抛受检异常,Callable 可以。
- 使用:Callable 常用于线程池提交任务。
40. 线程有哪些状态?
NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。
41. sleep() 和 wait() 有什么区别?
- sleep:Thread 静态方法,不释放锁,进入 TIMED_WAITING。
- wait:Object 实例方法,释放锁,进入 WAITING,需 notify 唤醒。
42. notify() 和 notifyAll() 有什么区别?
notify() 唤醒一个等待线程,notifyAll() 唤醒所有。生产消费模型中通常推荐 notifyAll() 以避免死锁风险。
43. 线程的 run() 和 start() 有什么区别?
start() 启动新线程执行 run();直接调用 run() 只是当前线程执行方法体,不会创建新线程。
44. 创建线程池有哪几种方式?
- ThreadPoolExecutor 构造函数(推荐)。
- Executors 工具类(FixedThreadPool 等)。
- Spring 配置。
45. 线程池都有哪些状态?
RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED。
46. 线程池中 submit() 和 execute() 方法有什么区别?
execute() 接受 Runnable,无返回值;submit() 接受 Runnable/Callable,返回 Future 对象,可获取结果或异常。
47. 在 java 程序中怎么保证多线程的运行安全?
使用 synchronized、Lock、volatile、原子类(Atomic)、线程安全集合、ThreadLocal 等机制。
48. 多线程锁的升级原理是什么?
无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁。根据竞争情况动态升级,减少系统开销。
49. 什么是死锁?
多个线程互相持有对方需要的资源,导致互相等待无法继续执行。
50. 怎么防止死锁?
避免嵌套锁、保持锁顺序一致、设置超时、使用 tryLock 等。
51. ThreadLocal 是什么?有哪些使用场景?
提供线程隔离的变量副本。场景:Web 请求上下文、数据库连接绑定、SimpleDateFormat 线程安全。
52. 说一下 synchronized 底层实现原理?
基于对象头(Mark Word)和 Monitor。JDK 6 后引入锁优化(偏向、轻量级)。
53. synchronized 和 volatile 的区别是什么?
- synchronized:保证原子性、可见性、有序性,重量级锁。
- volatile:保证可见性、有序性,不保证原子性,轻量级。
54. synchronized 和 Lock 有什么区别?
Lock 是接口(如 ReentrantLock),支持公平锁、中断响应、超时获取;synchronized 是关键字,隐式加锁,不可中断。
55. synchronized 和 ReentrantLock 区别是什么?
ReentrantLock 更灵活(tryLock、condition),synchronized 更简洁。JDK 6 后 synchronized 性能已优化。
56. 说一下 atomic 的原理?
基于 CAS(Compare-And-Swap)指令,硬件层面保证原子性,无锁编程。
四、反射
57. 什么是反射?
运行时动态获取类信息、调用方法、修改属性的机制。核心类:Class、Method、Field。
58. 什么是 java 序列化?什么情况下需要序列化?
将对象转为字节流。用于网络传输、持久化、RMI。需实现 Serializable 接口。
59. 动态代理是什么?有哪些应用?
运行时生成代理类。应用:Spring AOP、事务管理、RPC。
60. 怎么实现动态代理?
- JDK 动态代理(基于接口)。
- CGLIB 动态代理(基于继承)。
五、对象拷贝
61. 为什么要使用克隆?
避免浅拷贝带来的引用共享问题,实现对象独立副本。适用于原型模式、撤销重做。
62. 如何实现对象克隆?
实现 Cloneable 接口,重写 clone() 方法。注意深拷贝需递归复制引用对象。
63. 深拷贝和浅拷贝区别是什么?
浅拷贝只复制引用,深拷贝复制对象及其引用的所有对象。
六、异常
64. throw 和 throws 的区别?
throw 用于抛出具体异常对象;throws 用于声明方法可能抛出的异常类型。
65. final、finally、finalize 有什么区别?
final:修饰符,不可变;finally:异常处理块,必执行;finalize:GC 回收前调用(不推荐)。
66. try-catch-finally 中哪个部分可以省略?
try 必须存在。catch 和 finally 至少存在一个。
67. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
会。finally 会在方法真正返回前执行,但通常不能改变 catch 中设置的返回值。
68. 常见的异常类有哪些?
RuntimeException(NullPointerException, ArithmeticException 等),Checked Exception(IOException, SQLException 等)。
七、网络
69. http 响应码 301 和 302 代表的是什么?有什么区别?
301 永久重定向,SEO 权重传递;302 临时重定向,不传递权重。
70. forward 和 redirect 的区别?
forward 服务器内部转发,一次请求,URL 不变,可共享 request 数据;redirect 客户端重定向,两次请求,URL 变,不可共享 request 数据。
71. 简述 tcp 和 udp 的区别?
TCP 面向连接、可靠、慢;UDP 无连接、不可靠、快。
72. tcp 为什么要三次握手,两次不行吗?为什么?
三次握手是为了确认双方收发能力正常,并同步初始序列号。两次握手无法防止失效的连接请求突然传到服务端造成资源浪费。
73. 说一下 tcp 粘包是怎么产生的?
发送端使用 Nagle 算法合并小包,或接收端读取速度慢于写入速度,导致多个数据包在缓冲区堆积。
74. OSI 的七层模型都有哪些?
物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
75. get 和 post 请求有哪些区别?
GET 参数在 URL,幂等,可缓存;POST 参数在 Body,非幂等,不缓存,更安全。
76. 如何实现跨域?
CORS(推荐)、JSONP、反向代理、WebSocket 等。
77. 说一下 JSONP 实现原理?
利用 script 标签无同源限制,服务端返回 JS 函数调用,前端定义回调函数接收数据。
八、设计模式
78. 说一下你熟悉的设计模式?
单例、工厂、观察者、策略、装饰器、代理、模板方法、适配器。
79. 简单工厂和抽象工厂有什么区别?
简单工厂由一个类创建产品,违反开闭原则;抽象工厂创建一系列相关对象,符合开闭原则,扩展性好。
相关免费在线工具
- 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
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online