当前位置: 首页 > news >正文

Java核心面试技术

一、Java核心技术

1. 集合框架

HashMap 的实现原理?JDK 1.7 vs 1.8 区别?

  • JDK 1.7:
    • 数组 + 链表(拉链法)
    • 插入采用头插法,扩容时多线程下可能形成环形链表导致死循环
    • 初始容量 16,负载因子 0.75,扩容为原来 2 倍
  • JDK 1.8:
    • 数组 + 链表 + 红黑树
    • 当链表长度 ≥ 8 且数组长度 ≥ 64 时,链表转为红黑树
    • 使用尾插法,避免多线程死循环
    • 性能更稳定,最坏情况从 O(n) 提升到 O(log n)

核心原理:通过 hash 找到桶位置,解决冲突用链表/红黑树。


ConcurrentHashMap 如何保证线程安全?

  • JDK 1.7:分段锁(Segment),每段相当于一个小 HashMap,锁粒度为 Segment
  • JDK 1.8:
    • 放弃 Segment,使用 CAS + synchronized
    • 对 Node 数组的每个桶(bucket)加锁(synchronized 锁住链表头或红黑树根节点)
    • 插入、扩容等操作通过 CAS 配合 volatile 控制并发
    • 扩容时使用 transfer 机制,支持多线程协助迁移

优点:锁粒度更细,性能更高,避免 Segment 内存开销


ArrayList vs LinkedList

特性ArrayListLinkedList
底层结构 动态数组 双向链表
查询效率 O(1) O(n)
增删效率 尾部 O(1),中间 O(n) 任意位置 O(1)(已知节点)
扩容机制 扩容 1.5 倍(oldCapacity + (oldCapacity >> 1) 无固定容量,动态增删
内存占用 小(仅数组) 大(每个节点有 prev/next 指针)

适用场景:

  • ArrayList:读多写少,随机访问频繁
  • LinkedList:频繁在中间插入/删除,且不常随机访问

HashSet vs TreeSet

特性HashSetTreeSet
底层实现 HashMap(value 为 PRESENT TreeMap(红黑树)
排序 无序 自然排序或 Comparator 排序
时间复杂度 O(1) O(log n)
允许 null 允许一个 null null 取决于 Comparator(否则 NPE)

使用建议:

  • 快速查重 → HashSet
  • 需要有序集合 → TreeSet

fail-fast vs fail-safe

类型fail-fastfail-safe
实现机制 直接遍历原集合 遍历快照副本(如 CopyOnWriteArrayList)
是否抛异常 是(ConcurrentModificationException
常见集合 ArrayList, HashMap CopyOnWriteArrayList, ConcurrentHashMap
  • ConcurrentModificationException:modCount ≠ expectedModCount 时抛出
  • 避免方式:
    • 使用 Iterator.remove()
    • 使用并发集合(如 ConcurrentHashMap)
    • 使用 CopyOnWriteArrayList

Comparator vs Comparable

特性ComparableComparator
定义位置 类内部实现 compareTo() 外部定义 compare()
是否可变 固定一种排序逻辑 可定义多种排序策略
使用场景 默认排序(自然序) 自定义排序、多条件排序
java
深色版本
// Comparable
class Person implements Comparable<Person> {public int compareTo(Person p) { ... }
}// Comparator
Collections.sort(list, (a, b) -> a.age - b.age);

2. 多线程与并发

创建线程的方式

  1. 继承 Thread
  2. 实现 Runnable(无返回值)
  3. 实现 Callable(有返回值,配合 FutureTask
  4. 线程池提交任务(推荐)

Runnable vs Callable:

  • Runnable:run() 无返回值,不能抛 checked exception
  • Callable:call() 有返回值(Future),可抛异常

线程生命周期(6种状态)

java
深色版本
NEW -> RUNNABLE -> BLOCKED/WAITING/TIMED_WAITING -> TERMINATED
  • NEW:新建未启动
  • RUNNABLE:运行或就绪
  • BLOCKED:等待监视器锁
  • WAITING:无限等待(wait()join()
  • TIMED_WAITING:定时等待(sleep(1000)wait(1000)
  • TERMINATED:结束

synchronized 原理 & 锁升级

  • 对象头:包含 Mark Word(锁信息、GC 分代年龄、hashCode)
  • Monitor(管程):每个对象有一个 Monitor,控制同步
  • 锁升级过程:
    1. 无锁 → 2. 偏向锁(线程 ID 记录,避免重复加锁)→
    2. 轻量级锁(CAS 修改 Mark Word,自旋)→
    3. 重量级锁(阻塞,进入等待队列)

升级目的:减少线程阻塞带来的性能损耗


volatile 原理

  • 可见性:写操作后立即刷新到主内存,其他线程读取时强制从主存加载
  • 禁止指令重排:通过内存屏障(Memory Barrier)防止编译器/处理器重排序
  • 不保证原子性:如 i++ 仍需 synchronized 或 AtomicInteger

ReentrantLock vs synchronized

特性synchronizedReentrantLock
实现方式 JVM 内置 JDK 实现(AQS)
是否可中断 是(lockInterruptibly()
超时获取 是(tryLock(timeout)
公平锁 否(默认非公平) 可设置公平锁
条件变量 wait/notify Condition.await/signal
  • AQS(AbstractQueuedSynchronizer):
    • 使用 CLH 队列 管理等待线程
    • 通过 state 变量控制同步状态(0: 无锁, 1: 加锁)
    • 子类实现 tryAcquire/tryRelease 定义同步语义

ThreadPoolExecutor 核心参数

java
深色版本
new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,threadFactory,handler
);
  • corePoolSize:核心线程数(常驻)
  • maximumPoolSize:最大线程数
  • keepAliveTime:非核心线程空闲存活时间
  • workQueue:任务队列(ArrayBlockingQueue、LinkedBlockingQueue 等)
  • threadFactory:线程创建工厂
  • handler:拒绝策略(Abort, Discard, CallerRuns, DiscardOldest)

工作流程:

  1. ≤ core → 直接创建线程
  2. core,队列未满 → 入队

  3. core 且队列满 → 创建新线程 ≤ max

  4. max → 触发拒绝策略

常见线程池:

  • FixedThreadPool:固定大小,队列无界 → 易 OOM
  • CachedThreadPool:弹性,空闲 60s 回收 → 适合短任务
  • SingleThreadExecutor:单线程
  • ScheduledThreadPool:定时任务

合理配置:

  • CPU 密集型:N + 1
  • IO 密集型:2N ~ N/(1 - 阻塞系数)(如 2N)

ThreadLocal 原理 & 内存泄漏

  • 原理:每个线程持有 ThreadLocalMap,key 为 ThreadLocal 实例(弱引用),value 为值
  • 内存泄漏原因:
    • key 是弱引用,GC 后 key 为 null
    • 但 value 强引用未清理 → 内存泄漏
  • 解决方案:
    • 调用 remove() 主动清理
    • 使用静态 ThreadLocal + try-finally 模式

应用场景:

  • 用户上下文传递(如 UserContext
  • 数据库连接管理
  • 事务管理

并发工具类

工具类用途示例
CountDownLatch 等待 N 个线程完成 主线程等子线程
CyclicBarrier N 个线程互相等待,到达屏障后一起执行 并发测试
Semaphore 控制并发访问资源数量 限流
Exchanger 两个线程交换数据 生产者-消费者

3. I/O

NIO vs BIO

特性BIONIO
模型 阻塞 I/O 非阻塞 I/O(多路复用)
核心组件 Stream Buffer, Channel, Selector
连接数 少连接 高并发(C10K)
编程复杂度 简单 复杂

NIO 优势:单线程处理多个连接(Selector 监听事件)


序列化与 transient

  • 序列化:对象 → 字节流(ObjectOutputStream
  • transient:标记字段不参与序列化
  • 常见协议:JDK 原生、JSON、XML、Hessian、Protobuf、Kryo

缓冲流作用

  • BufferedInputStream:减少系统调用次数,提升 I/O 效率
  • 原因:直接读文件每次系统调用开销大;缓冲流先读一块到内存,再逐字节读

4. JDBC

JDBC 步骤

  1. 加载驱动:Class.forName("com.mysql.cj.jdbc.Driver")
  2. 获取连接:DriverManager.getConnection(url, user, pwd)
  3. 创建 Statement
  4. 执行 SQL
  5. 处理结果集
  6. 关闭资源(try-with-resources)

PreparedStatement vs Statement

特性PreparedStatementStatement
SQL 注入 防止(预编译) 不防
性能 预编译,缓存执行计划 每次编译
参数设置 setString(1, "xxx") 字符串拼接

推荐使用 PreparedStatement


事务 ACID

  • Atomicity:原子性(全成功或全失败)
  • Consistency:一致性(状态合法)
  • Isolation:隔离性(并发不影响)
  • Durability:持久性(提交后不丢失)

JDBC 事务管理:

java
深色版本
conn.setAutoCommit(false);
try {// 执行 SQLconn.commit();
} catch (Exception e) {conn.rollback();
}

数据库连接池原理

  • 预创建连接,复用连接,避免频繁创建销毁
  • 管理连接生命周期、超时、最大连接数
  • 常见连接池:HikariCP(性能最好)、Druid(功能丰富,监控强)

5. 反射

反射原理

  • 运行时获取类信息(字段、方法、构造器)
  • 动态创建对象、调用方法

Class 获取方式:

  • obj.getClass()
  • 类名.class
  • Class.forName("全限定名")

forName() 会触发类初始化,.class 不会


应用场景

  • 框架(Spring IOC、MyBatis)
  • 动态代理
  • ORM 映射
  • 注解处理

二、Java Web & 主流框架

Spring Framework

IoC / DI

  • IoC:控制反转,由容器管理对象生命周期
  • DI:依赖注入,自动装配依赖
  • 注入方式:
    • 构造器(推荐,不可变)
    • Setter(可选依赖)
    • 字段(方便,但不利于测试)

作用域:

  • singleton:单例(默认)
  • prototype:每次获取新实例
  • request/session/application:Web 作用域

AOP

  • 解决:横切关注点(日志、事务、权限)
  • 核心概念:
    • 切面(Aspect):横切逻辑模块
    • 通知(Advice):@Before@After@Around
    • 切入点(Pointcut):匹配连接点的表达式
    • 连接点(JoinPoint):方法执行点

动态代理:

  • JDK Proxy:基于接口
  • CGLIB:基于子类(无接口可用)

Spring AOP vs AspectJ:

  • Spring AOP:运行时代理,功能有限
  • AspectJ:编译期织入,功能强大

Spring MVC 流程

  1. 前端请求 → DispatcherServlet
  2. HandlerMapping 查找处理器
  3. HandlerAdapter 调用 Controller
  4. 返回 ModelAndView
  5. ViewResolver 解析视图
  6. 渲染响应

常用注解:

  • @Controller:控制器
  • @RequestMapping:映射路径
  • @ResponseBody:返回 JSON
  • @RestController = @Controller + @ResponseBody

Spring 事务管理

  • 传播行为:
    • REQUIRED:有则加入,无则新建(最常用)
    • REQUIRES_NEW:挂起当前,新建事务
  • 隔离级别:对应数据库
  • @Transactional 失效场景:
    • 方法非 public
    • 自调用(this.method())
    • 异常被捕获未抛出
    • 代理未生效(如未扫描包)

Spring Boot

核心优势

  • 自动配置(@EnableAutoConfiguration
  • 起步依赖(starter)
  • 内嵌容器(Tomcat/Jetty)

@SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan


自动配置原理

  • spring.factories 中定义 @Configuration 类
  • 使用 @ConditionalOnXXX 条件注解按需加载

自定义 Starter

  1. xx-spring-boot-autoconfigure
  2. spring.factories 配置 EnableAutoConfiguration
  3. 条件装配 Bean
  4. 提供默认配置属性(@ConfigurationProperties

MyBatis

#{} vs ${}

  • #{}:预编译参数(安全,防 SQL 注入)
  • ${}:字符串替换(不安全,用于动态表名、排序字段)

动态 SQL

xml
深色版本
<if test="name != null"> AND name = #{name} </if>
<choose><when test="id != null">id = #{id}</when><otherwise>name = #{name}</otherwise>
</choose>
<foreach collection="list" item="item" separator=","> #{item} </foreach>

分页

  • PageHelper:拦截 Executor.query,重写 SQL 加 LIMIT
  • 物理分页:数据库 LIMIT(推荐)
  • 逻辑分页:查所有再内存分页(不推荐)

延迟加载

  • 原理:关联对象在使用时才查询(通过代理)
  • 配置:lazyLoadingEnabled=true
  • N+1 问题解决:
    • 使用 JOIN 查询一次性加载
    • 使用 fetchType="eager" 强制立即加载

一级缓存 & 二级缓存

  • 一级缓存:SqlSession 级别,自动开启
  • 二级缓存:Mapper 级别,需手动开启(<cache/>),序列化支持
  • 失效:执行 commit()clearCache()update 操作

三、数据库(MySQL)

索引优化

  • B+树优势:
    • 层高低(3层可存千万级)
    • 叶子节点有序、链表连接,适合范围查询
  • 聚集索引:主键索引,数据存于叶子节点
  • 非聚集索引:二级索引,叶子存主键值
  • 覆盖索引:查询字段全在索引中,无需回表

事务隔离级别

级别脏读不可重复读幻读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ(MySQL 默认) ❌(MVCC + Gap Lock)
SERIALIZABLE

MVCC 原理

  • 多版本并发控制,提升读并发
  • 基于 undo log 保存历史版本
  • ReadView 判断哪些版本可见

Redis

数据类型 & 场景

类型场景
String 缓存、计数器
Hash 用户信息、购物车
List 消息队列、最新列表
Set 去重、共同关注
ZSet 排行榜、延迟队列

持久化

  • RDB:定时快照,恢复快,可能丢数据
  • AOF:日志追加,数据安全,文件大
  • 混合模式(4.0+):RDB 快照 + AOF 增量

缓存问题

问题解决方案
穿透 布隆过滤器、缓存空值
击穿 互斥锁、热点永不过期
雪崩 随机过期时间、集群、降级

一致性方案

  • 先更新 DB → 删除缓存(推荐)
  • 延迟双删
  • 监听 binlog(Canal)异步更新缓存

四、前端(Vue2 + Element-UI)

Vue 2 响应式原理

  • Object.defineProperty 劫持 get/set
  • get 收集依赖(Watcher)
  • set 派发更新
  • 数组通过重写 push/pop/splice 等方法监听

局限性:

  • 无法监听属性添加/删除
  • 数组索引修改、length 变化不响应 → Vue.set() / vm.$set()

Vuex

  • State:状态源
  • Getter:计算属性
  • Mutation:同步修改状态(必须)
  • Action:异步操作,提交 Mutation
  • Module:模块化

Mutation 同步:便于 DevTools 跟踪状态变化


五、开发工具

Git

  • rebase:变基,提交历史更干净
  • merge:合并,保留分支历史
  • Git Flow:masterdevelopfeaturereleasehotfix

六、项目经验(MES系统)

⚠️ 这是重中之重!建议准备 2-3 个真实案例,结合 STAR 法则(Situation, Task, Action, Result)讲述

示例回答(高并发包装关箱):

S:MES 系统中,包装工位扫码速度极快,高峰期每秒数十次请求,导致数据库锁竞争严重。

T:需保证包装数据准确,避免重复包装或漏记。

A:

  • 使用 Redis 分布式锁(Redisson)控制同一 SN 的并发操作
  • 包装计数使用 INCR 原子操作
  • 关键操作日志异步落库
  • 数据库分表(按订单 ID)

R:系统吞吐提升 5 倍,零重复包装错误,响应时间 < 200ms。

http://www.sczhlp.com/news/269.html

相关文章:

  • 人力资源各系统的关联与一体化趋势:从独立到协同的必然之路
  • 评估Gitee作为DevOps平台:功能详解与适用性分析
  • business
  • 4、如何给一万张图片重命名
  • 基于FFmpeg开发的在线m3u8转MP4在线工具(开发步骤+类库)
  • 米牛图片搬运去重大师手机版使用教程
  • debian12 修改源为阿里
  • 分享一个 AI 自动生成流程图的工具
  • Charles抓包iPhone踩坑(自用)
  • 16Java基础之枚举、泛型、API、Objects类、包装类
  • 卷积神经网络的验证码识别系统设计与实现
  • Git 提交信息(Commit Message)前缀规范
  • Visual Studio中的常用调试功能(二)
  • 易基因突破创新 自主研发DNA甲基化年龄预测算法及系统获发明专利授权
  • 从独立工具到协作中枢:Bug管理系统的进化革命
  • Redis的引入与配置
  • 给删除增加删除感
  • 卷积神经网络的验证码识别系统设计
  • scrollTop
  • 阿里云OSS 的Content-Disposition不生效 导致浏览器强制下载而不是预览行为
  • 测试
  • AI测试开发私教服务全新升级
  • 10分钟无痛部署!字节Coze开源版喂饭教程
  • 28 位运算
  • Prime Video如何将时间序列异常转化为可操作警报
  • 抗原设计与合成服务|定制抗原技术|高效多肽合成
  • 中日甲午海战军舰情况
  • 面试算法练习-更新ing
  • 2025年优选代码托管平台指南
  • 重塑应用搜索体验,系统级入口功能一步直达