[Java基础]高频面试题
1. 面向对象三大特性及实际应用
问题:请解释Java面向对象的三大特性,并举例说明在实际开发中的应用。
答:
- 封装:隐藏对象的属性和实现细节,仅对外公开接口。例如:将类的成员变量设为private,通过public的getter/setter方法访问18
- 继承:子类继承父类的特征和行为。例如:
ArrayList继承AbstractList,复用父类的通用方法1 - 多态:同一操作作用于不同对象产生不同行为。例如:
List list = new ArrayList(),编译看左边,运行看右边1
实际应用:
- 封装:DTO对象隐藏数据库字段细节
- 继承:自定义异常继承
RuntimeException - 多态:Spring依赖注入时使用接口类型接收实现类
2. ==和equals的区别
问题:详细说明==和equals的区别,并解释为什么重写equals时要重写hashCode?
答:
- ==:基本类型比较值,引用类型比较内存地址16
- equals:默认比较地址(Object类实现),可被重写为内容比较(如String)6
重写equals必须重写hashCode的原因:
- 违反
equals相等则hashCode必须相等的约定会导致HashSet/HashMap等集合类工作异常9 - 例如:两个内容相同的对象equals返回true但hashCode不同,会导致HashMap中重复存储
3. String、StringBuilder和StringBuffer的区别
问题:比较String、StringBuilder和StringBuffer的特性及使用场景。
答案:
| 特性 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 可变性 | 不可变(immutable) | 可变(mutable) | 可变(mutable) |
| 线程安全 | 线程安全 | 非线程安全 | 线程安全(synchronized) |
| 性能 | 低(频繁操作时) | 高 | 中等(有同步开销) |
| 使用场景 | 少量字符串操作 | 单线程大量字符串操作 | 多线程大量字符串操作 |
原理:String使用final char[]存储,每次修改都创建新对象;StringBuilder/Buffer使用普通char[],可动态扩容
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记及答案【扫一扫】 即可免费获取**
Java集合框架高频面试题
1. HashMap底层原理及线程安全问题
问题:详细说明JDK8中HashMap的实现原理,包括put过程、扩容机制和线程安全问题。
答:
数据结构:数组+链表+红黑树(链表长度>8且数组长度≥64时转换)19
put过程:
-
计算key的hash:(h = key.hashCode()) ^ (h >>> 16)9
-
找到数组下标:(n-1) & hash
-
处理碰撞:
- 无碰撞:直接存入Node
- 链表碰撞:尾插法(JDK8),长度达8转红黑树
- 红黑树碰撞:按树结构插入
扩容机制:
- 触发条件:size > threshold(容量*负载因子0.75)1
- 扩容过程:创建新数组(2倍),rehash所有元素
- JDK8优化:无需重新计算hash,通过(e.hash & oldCap)判断位置1
线程安全问题:
- 并发put可能导致数据覆盖或链表成环(JDK7)1
- 解决方案:使用ConcurrentHashMap(JDK8采用synchronized+CAS)1
2. ConcurrentHashMap的实现原理
问题:JDK8中ConcurrentHashMap如何保证线程安全?与Hashtable有什么区别?
答:
JDK8实现:
-
数据结构:Node数组+链表+红黑树(类似HashMap)1
-
线程安全机制:
- CAS初始化数组
- synchronized锁链表头/树根(粒度更细)1
- 多线程协助扩容
与Hashtable对比:
| 特性 | ConcurrentHashMap(JDK8) | Hashtable |
|---|---|---|
| 锁粒度 | 桶级别(synchronized) | 整个表(synchronized) |
| 并发性能 | 高 | 低 |
| 空值支持 | 不允许null键/值 | 不允许null键/值 |
| 迭代器 | 弱一致性 | 快速失败 |
使用场景:高并发环境下替代Hashtable8
Java多线程与并发高频面试题
1. synchronized和ReentrantLock的区别
问题:比较synchronized和ReentrantLock的异同,并说明各自适用场景。
答:
对比:
| 特性 | synchronized | ReentrantLock |
|---|---|---|
| 实现层面 | JVM层面(monitorenter/monitorexit) | API层面(Java代码实现) |
| 锁获取与释放 | 自动 | 必须手动lock/unlock |
| 尝试非阻塞获取锁 | 不支持 | tryLock()支持 |
| 公平锁 | 非公平 | 可配置公平/非公平 |
| 条件变量 | 单一wait/notify | 支持多个Condition |
| 锁中断 | 不支持 | lockInterruptibly()支持 |
| 性能 | JDK6后优化,性能接近 | 高竞争下表现更好 |
适用场景:
- synchronized:简单同步场景,代码简洁优先
- ReentrantLock:需要高级功能(如定时锁等待、公平锁、可中断锁)18
2. volatile关键字的作用
问题:volatile关键字解决了什么问题?如何保证可见性和有序性?
答:
解决的问题:
- 可见性问题:多线程间共享变量的即时可见
- 有序性问题:防止指令重排序
实现原理:
- 可见性:写操作立即刷新到主内存,读操作直接从主内存读取1
- 有序性:插入内存屏障(LoadLoad, LoadStore, StoreLoad, StoreStore)1
局限性:
- 不保证原子性(如i++)1
- 适用场景:单线程写多线程读,或作为状态标志位
JVM高频面试题
1. JVM内存结构及GC原理
问题:描述JVM内存结构,并说明各区域GC机制。
答:
内存结构:
- 程序计数器:线程私有,记录执行位置7
- 虚拟机栈:线程私有,存储栈帧(局部变量表、操作数栈等)7
- 本地方法栈:Native方法服务7
- 堆:所有对象实例和数组,分新生代(Eden/S0/S1)和老年代7
- 方法区(元空间) :类信息、常量、静态变量等7
GC机制:
| 区域 | GC算法 | 触发条件 |
|---|---|---|
| 新生代 | 复制算法 | Eden区满 |
| 老年代 | 标记-清除/标记-整理 | 老年代空间不足 |
| 元空间 | 无特定GC | 类卸载时回收 |
常见GC组合:
- Serial/Serial Old
- ParNew/CMS
- G1(JDK9默认)7
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记及答案【扫一扫】 即可免费获取**
2. 类加载过程及双亲委派模型
问题:描述类加载过程,并解释双亲委派模型及其打破场景。
答:
类加载过程:
- 加载:获取二进制流,生成Class对象7
- 验证:文件格式、元数据、字节码等验证7
- 准备:为静态变量分配内存并设默认值7
- 解析:符号引用转直接引用7
- 初始化:执行静态代码块和静态变量赋值7
双亲委派模型:
- 类加载器层次:Bootstrap → Extension → Application → 自定义7
- 工作流程:子类加载器先委托父类加载,父类无法完成才自己加载7
- 优点:避免重复加载,保证核心类安全
打破场景:
- SPI机制(如JDBC):Bootstrap加载器委托线程上下文类加载器加载实现类7
- OSGi:模块化热部署需求
- 自定义类加载器重写loadClass方法
Spring框架高频面试题
1. Spring Bean生命周期
问题:详细描述Spring Bean的生命周期。
答:
完整生命周期:
- 实例化(通过构造器或工厂方法)
- 属性赋值(依赖注入)
- BeanNameAware.setBeanName()
- BeanFactoryAware.setBeanFactory()
- ApplicationContextAware.setApplicationContext()
- BeanPostProcessor.postProcessBeforeInitialization()
- InitializingBean.afterPropertiesSet()
- 自定义init-method
- BeanPostProcessor.postProcessAfterInitialization()
- 使用中
- DisposableBean.destroy()
- 自定义destroy-method
关键扩展点:
- Aware接口:获取容器基础设施
- BeanPostProcessor:前后置处理
- InitializingBean/DisposableBean:初始化/销毁逻辑4
2. Spring事务传播机制
问题:解释Spring事务的七种传播行为及其应用场景。
答:
| 传播行为 | 描述 | 适用场景 |
|---|---|---|
| REQUIRED(默认) | 当前有事务则加入,没有则新建 | 大多数业务方法 |
| SUPPORTS | 当前有事务则加入,没有则以非事务运行 | 查询方法,可适应事务或非事务环境 |
| MANDATORY | 当前必须有事务,否则抛异常 | 必须被事务方法调用的方法 |
| REQUIRES_NEW | 新建事务,挂起当前事务(若有) | 独立事务操作(如日志记录) |
| NOT_SUPPORTED | 以非事务方式执行,挂起当前事务(若有) | 不需要事务支持的操作 |
| NEVER | 以非事务方式执行,当前有事务则抛异常 | 必须非事务执行的方法 |
| NESTED | 在当前事务中嵌套子事务(保存点),子事务回滚不影响父事务 | 复杂业务中的部分可回滚操作 |
实现原理:基于数据库保存点(JDBC)或JTA分布式事务管理
数据库与缓存高频面试题
1. MySQL索引优化
问题:MySQL索引失效的常见场景及优化建议。
答:
失效场景:
- 违反最左前缀原则:联合索引(a,b,c)但条件无a
- 对索引列运算或函数:
WHERE YEAR(create_time)=2025 - 隐式类型转换:字符串列用数字查询
- 使用!=或<>操作符
- LIKE以通配符开头:
LIKE '%abc' - OR条件中部分无索引
- 估计全表扫描更快(数据量小或高重复值)
优化建议:
- 合理设计联合索引顺序(区分度高在前)
- 使用覆盖索引避免回表
- 避免SELECT *,只查询必要字段
- 大数据量表考虑分区或分表
- 定期ANALYZE TABLE更新统计信息
2. Redis缓存穿透/雪崩/击穿解决方案
问题:解释Redis缓存穿透、雪崩和击穿现象及解决方案。
答:
缓存穿透:
-
现象:查询不存在的数据(恶意攻击),绕过缓存直击数据库
-
解决:
- 布隆过滤器预判key是否存在
- 缓存空对象(设置短TTL)
- 接口层校验参数合法性
缓存雪崩:
-
现象:大量key同时过期,导致请求集中访问数据库
-
解决:
- 设置随机过期时间(基础时间+随机值)
- 热点数据永不过期,后台异步更新
- 多级缓存架构(本地缓存+Redis)
缓存击穿:
-
现象:热点key过期瞬间,大量请求直接访问数据库
-
解决:
- 互斥锁(setnx):只允许一个请求重建缓存
- 逻辑过期:不设置TTL,程序判断是否需更新
- 永不过期+后台更新策略
系统设计高频面试题
1. 分布式ID生成方案
问题:常见的分布式ID生成方案及其优缺点比较。
答:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| UUID | 简单,本地生成无网络开销 | 无序,存储空间大,索引效率低 | 简单场景,不关心有序性 |
| 数据库自增ID | 简单,严格递增 | 单点故障,性能瓶颈 | 小规模系统 |
| Redis INCR | 性能较好,原子性递增 | 依赖Redis可用性 | 已有Redis环境 |
| 雪花算法(Snowflake) | 趋势递增,高性能,去中心化 | 依赖机器时钟(时钟回拨问题) | 大规模分布式系统 |
| 号段模式 | 减少数据库访问,性能好 | 需要维护号段状态 | 中大规模系统 |
Snowflake详解:64位=1(符号)+41(时间戳)+10(机器ID)+12(序列号)10
2. 分布式锁实现方案
问题:比较Redis和Zookeeper实现分布式锁的机制及优劣。
答:
Redis实现:
-
机制:SETNX+过期时间,Lua脚本保证原子性
-
优点:性能高,实现简单
-
缺点:
- 锁自动过期导致误删(需value唯一标识)
- 主从切换可能丢失锁
-
优化:Redlock算法(多实例投票)10
Zookeeper实现:
-
机制:创建临时有序节点,最小节点获取锁
-
优点:
- 原生支持(临时节点+Watch机制)
- 无超时问题,可靠性高
-
缺点:性能较低,需维护ZK集群
选型建议:
- CP需求(强一致性):Zookeeper
- AP需求(高可用):Redis
- 超高并发:考虑分段锁或乐观锁
场景设计高频面试题
1. 秒杀系统设计要点
问题:设计一个高并发秒杀系统需要考虑哪些关键点?
答:
核心挑战:
- 瞬时高并发
- 超卖问题
- 系统稳定性
解决方案:
-
架构分层:
- 前端:静态资源CDN,按钮防重复点击
- 网关:限流(令牌桶/漏桶),黑名单
- 服务:无状态设计,弹性扩容
-
库存处理:
- Redis预减库存(原子操作DECR)
- 异步扣库存(消息队列+数据库事务)
- 库存分段(减小锁粒度)
-
热点数据:
- 本地缓存+Redis多级缓存
- 库存数据分片存储
-
防作弊:
- 风控系统(IP/设备指纹限流)
- 验证码/答题机制
-
降级预案:
- 熔断机制(Hystrix/Sentinel)
- 排队系统(虚拟队列)
- 降级策略(静态页兜底)10
2. 分布式事务解决方案
问题:常见的分布式事务解决方案及其适用场景。
答:
| 方案 | 原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 2PC(两阶段提交) | 协调者准备阶段+提交/回滚阶段 | 强一致性 | 同步阻塞,单点故障 | 传统数据库跨库事务 |
| TCC(Try-Confirm-Cancel) | 业务拆分三个阶段 | 高并发适应 | 业务侵入性强 | 金融支付等高一致性场景 |
| 本地消息表 | 本地事务+异步消息 | 简单,最终一致 | 消息处理需幂等 | 跨系统数据同步 |
| Saga | 长事务拆分为多个本地事务+补偿 | 适合长流程业务 | 需设计完备补偿机制 | 订单/物流等流程型业务 |
| 最大努力通知 | 定期重试通知 | 实现简单 | 一致性最弱 | 对实时性要求不高的场景 |
选型建议:
- 强一致性:TCC
- 最终一致:本地消息表/Saga
- 简单场景:最大努力通知[c