```html
欢迎访问经典java面试题备考平台 - 助您斩获大厂Offer 域名:www.kaoacca.cn

经典java面试题深度解析与备考指南

汇聚互联网大厂高频考点,从Java基础到分布式架构,为您提供全方位的技术面试辅导。无论您是初出茅庐的应届生,还是寻求突破的中高级开发者,这里都能找到您需要的知识体系。

#Java基础 #JVM调优 #SpringBoot #微服务 #高并发

一、Java基础核心考点

基础不牢,地动山摇。以下是面试官最爱问的Java基础问题。

面向对象特性详解

封装、继承、多态是Java的三大特性。其中,多态是面试中的高频词。多态分为编译时多态(方法重载)和运行时多态(方法重写)。实现多态的三个必要条件:继承、方法重写、父类引用指向子类对象。

  • 封装:隐藏内部实现,暴露公共接口
  • 继承:代码复用,单继承多实现
  • 多态:同一行为,多种形态

String类深度剖析

String类在Java中是不可变的(final)。这种设计带来了线程安全和缓存复用的优势。面试常问String、StringBuilder、StringBuffer的区别:

  • String:不可变,线程安全
  • StringBuilder:可变,非线程安全,速度快
  • StringBuffer:可变,线程安全,速度慢

Equals与==的区别

“==”比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正的几何意义上的相等。

“equals”用来比较的是两个对象的内容是否相等。若没有重写equals方法,默认调用的是Object类的equals方法,其实现也是“==”。String类重写了equals方法,比较的是字符串内容。

二、集合框架核心机制

ArrayList vs LinkedList

ArrayList是基于动态数组的数据结构,查询速度快(O(1)),但增删速度慢(需要移动元素)。适用于读多写少的场景。

LinkedList是基于双向链表的数据结构,增删速度快(O(1)),但查询速度慢(O(n))。适用于写多读少的场景,如队列实现。

Vector的特殊性

Vector是线程安全的集合,其方法大多使用synchronized修饰。由于性能较差,在现代Java开发中已较少使用,通常被ArrayList或CopyOnWriteArrayList取代。

HashMap底层原理

HashMap在JDK1.7中是数组+链表,在JDK1.8中引入了红黑树。当链表长度超过8且数组长度超过64时,链表转换为红黑树,以提高查询效率(从O(n)提升至O(log n))。

HashMap不是线程安全的。在并发环境下,建议使用ConcurrentHashMap。

ConcurrentHashMap

JDK1.7采用分段锁(Segment),JDK1.8采用CAS+synchronized。Node节点的值和next引用都是volatile修饰,保证可见性。线程安全性高,性能优异。

HashSet与HashMap

HashSet底层实际上就是HashMap。HashSet添加元素时,将元素作为HashMap的Key,而Value是一个固定的Object对象(PRESENT)。因此,HashSet中的元素也是不能重复的,且不保证顺序。

三、并发编程进阶

高并发是Java后端开发的灵魂,也是区分初级与高级开发者的分水岭。

线程池核心参数

创建线程池时,必须明确7大核心参数:corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(空闲线程存活时间)、unit(时间单位)、workQueue(任务队列)、threadFactory(线程工厂)、handler(拒绝策略)。

面试常问:为什么不建议使用Executors创建线程池?因为FixedThreadPool和SingleThreadPool允许的请求队列长度为Integer.MAX_VALUE,可能堆积大量请求导致OOM。

synchronized vs ReentrantLock

synchronized是JVM层面的关键字,自动加锁解锁,不可中断,非公平锁。

ReentrantLock是API层面的锁,需要手动lock/unlock,可中断,支持公平锁,支持Condition条件变量。在复杂并发场景下,ReentrantLock更灵活。

volatile关键字

volatile保证变量的可见性,不保证原子性。它通过内存屏障禁止指令重排序。适用于“一个写线程,多个读线程”的场景,或者状态标志位。

四、JVM内存模型与调优

内存区域 线程共享 存储内容 常见异常
堆内存 (Heap) 是 对象实例、数组 OutOfMemoryError
方法区 (Method Area) 是 类信息、常量、静态变量 OutOfMemoryError
虚拟机栈 (VM Stack) 否 局部变量表、操作数栈 StackOverflowError
本地方法栈 (Native Stack) 否 Native方法服务 StackOverflowError
程序计数器 (PC Register) 否 当前线程执行的字节码行号 无

垃圾回收算法

标记-清除:产生内存碎片。标记-复制:适用于年轻代,无碎片。标记-整理:适用于老年代,无碎片。

常见GC收集器:Serial、ParNew、Parallel Scavenge、CMS(并发标记清除)、G1(Region区域化)、ZGC(低延迟)。

五、Spring全家桶生态

Spring IOC与AOP

IOC(控制反转):将对象的创建权交给Spring容器,通过依赖注入(DI)实现解耦。常用注解:@Component, @Service, @Autowired。

AOP(面向切面编程):将日志、事务、权限等横切关注点与业务逻辑分离。底层实现:JDK动态代理(接口)和CGLIB(类)。

Spring Bean生命周期

1. 实例化Bean(Instantiation)

2. 属性赋值(Populate Bean)

3. 初始化(Initialization):调用InitializingBean、@PostConstruct、init-method

4. 使用Bean

5. 销毁(Destruction):调用DisposableBean、@PreDestroy、destroy-method

Spring Boot自动装配原理

核心注解:@SpringBootApplication,其中包含@EnableAutoConfiguration。该注解通过导入AutoConfigurationImportSelector,加载META-INF/spring.factories中的配置类,实现自动装配。

六、数据库与MySQL优化

索引底层数据结构

MySQL InnoDB引擎默认使用B+树作为索引结构。相比B树,B+树所有数据都在叶子节点,非叶子节点只存储键值,使得树更矮胖,查询效率更稳定。叶子节点之间通过双向链表连接,适合范围查询。

事务隔离级别

  • 读未提交(Read Uncommitted):可能发生脏读、不可重复读、幻读
  • 读已提交(Read Committed):避免脏读,可能发生不可重复读、幻读(Oracle默认)
  • 可重复读(Repeatable Read):避免脏读、不可重复读,可能发生幻读(MySQL默认)
  • 串行化(Serializable):避免所有问题,性能最低

MySQL通过MVCC(多版本并发控制)和锁机制实现可重复读。

七、分布式架构与微服务

Redis缓存穿透/击穿/雪崩

缓存穿透:查询不存在的数据。解决:布隆过滤器、缓存空对象。

缓存击穿:热点Key过期,大量请求打到数据库。解决:互斥锁、逻辑过期。

缓存雪崩:大量Key同时过期或Redis宕机。解决:随机过期时间、集群部署、限流降级。

消息队列RabbitMQ/Kafka

应用场景:异步处理、流量削峰、解耦。

RabbitMQ:基于Erlang,延迟低,适合金融场景,支持复杂路由。

Kafka:基于Scala,吞吐量极高,适合日志收集、大数据处理。

网友们还关心

高频面试问答FAQ

Q: Java中接口(Interface)和抽象类(Abstract Class)的区别?

1. 设计层面:接口是对“Has-A”关系的抽象,抽象类是对“Is-A”关系的抽象。2. 方法实现:Java 8之前接口不能有方法体,现在可以有default和static方法;抽象类可以有普通方法。3. 继承限制:类只能单继承抽象类,但可以实现多个接口。4. 成员变量:接口变量默认是public static final,抽象类可以是任意类型。

Q: 什么是深拷贝和浅拷贝?

浅拷贝(Shallow Copy):复制基本类型,引用类型只复制地址。深拷贝(Deep Copy):复制基本类型,引用类型也创建新对象。在Java中,实现Cloneable接口并重写clone()方法可实现浅拷贝,深拷贝通常需要序列化或手动递归复制。

Q: HTTP与HTTPS的区别?

1. 安全性:HTTPS使用SSL/TLS加密,HTTP明文传输。2. 端口:HTTP默认80,HTTPS默认443。3. 证书:HTTPS需要CA证书。4. 性能:HTTPS握手过程比HTTP复杂,性能略低,但现代硬件已大幅优化。

Q: 如何解决数据库慢查询?

1. 使用EXPLAIN分析执行计划,检查是否走索引。2. 优化SQL语句,避免SELECT ,避免在索引列上做计算。3. 添加合适的索引,注意最左前缀原则。4. 分库分表,读写分离。5. 优化表结构,减少字段长度。

```
斌知网
蜀ICP备2026017620号-5