应届毕业生计算机专业常见面试题
一、Java 基础
1.1 基本概念
Q:Java 中 == 和 equals 的区别?
==比较的是引用地址(基本类型比较值)equals比较的是对象内容(默认行为同==,String等类已重写)
String a = new String("hello");
String b = new String("hello");
a == b; // false,不同对象
a.equals(b); // true,内容相同
Q:String、StringBuilder、StringBuffer 的区别?
| 对比项 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 可变性 | 不可变 | 可变 | 可变 |
| 线程安全 | 安全(不可变) | 不安全 | 安全(synchronized) |
| 性能 | 拼接时产生大量临时对象 | 最快 | 略慢于 StringBuilder |
| 使用场景 | 少量字符串操作 | 单线程大量拼接 | 多线程大量拼接 |
Q:final、finally、finalize 的区别?
final:修饰类不可继承,修饰方法不可重写,修饰变量不可再赋值finally:try-catch-finally 中无论是否异常都会执行的代码块(除 JVM 退出或线程被杀)finalize:Object 类的方法,GC 回收前调用(Java 9 已标记废弃,不推荐依赖)
Q:重载(Overload)和重写(Override)的区别?
| 对比项 | 重载 | 重写 |
|---|---|---|
| 发生范围 | 同一个类 | 子类与父类 |
| 方法名 | 相同 | 相同 |
| 参数列表 | 必须不同 | 必须相同 |
| 返回值 | 可不同 | 相同或协变 |
| 访问修饰符 | 可不同 | 不能更严格 |
1.2 集合框架
Q:ArrayList 和 LinkedList 的区别?
| 对比项 | ArrayList | LinkedList |
|---|---|---|
| 底层结构 | 动态数组 | 双向链表 |
| 随机访问 | O(1) | O(n) |
| 头部插入/删除 | O(n) | O(1) |
| 尾部插入 | 均摊 O(1) | O(1) |
| 内存占用 | 紧凑 | 每个节点额外存储前后指针 |
| 扩容机制 | 1.5 倍扩容 | 无需扩容 |
Q:HashMap 的底层原理?
核心结构:数组 + 链表 + 红黑树(JDK 8)
put 流程:
1. 计算 key 的 hash 值,通过 (n - 1) & hash 定位桶位置
2. 桶为空 → 直接放入
3. 桶不为空 → 遍历链表
a. key 已存在 → 覆盖旧值
b. key 不存在 → 尾插法添加
c. 链表长度 >= 8 且数组长度 >= 64 → 转为红黑树
4. size > threshold(容量 × 负载因子 0.75)→ 扩容为 2 倍
Q:HashMap 为什么线程不安全?
- JDK 7:多线程扩容时可能产生环形链表,导致死循环
- JDK 8:多线程 put 时可能丢失数据、覆盖已有值
Q:ConcurrentHashMap 是如何保证线程安全的?
- JDK 7:
Segment数组 +HashEntry,每个 Segment 是一把锁(分段锁) - JDK 8:CAS +
synchronized,锁粒度从 Segment 级别降为桶(首节点)级别
1.3 多线程
Q:线程的创建方式?
- 继承
Thread类,重写run() - 实现
Runnable接口 - 实现
Callable<V>接口(有返回值,配合 Future) - 线程池
ExecutorService(推荐)
Q:synchronized 和 ReentrantLock 的区别?
| 对比项 | synchronized | ReentrantLock |
|---|---|---|
| 锁类型 | JVM 层面(monitorenter) | API 层面(java.util.concurrent) |
| 是否可中断 | 不可中断 | lockInterruptibly() 可中断 |
| 是否公平锁 | 非公平 | 支持公平/非公平 |
| 条件绑定 | 单一条件(wait/notify) | 多条件(Condition) |
| 释放锁 | 自动释放(作用域结束) | 必须 unlock()(finally 中释放) |
Q:volatile 关键字的作用?
两个作用:
- 可见性:修改后立即刷新到主内存,其他线程读取时从主内存获取
- 禁止指令重排序:通过内存屏障防止编译器和 CPU 重排
不保证原子性,i++ 仍需要加锁或使用 AtomicInteger。
Q:线程池的核心参数?
ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 非核心线程空闲存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 任务队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)
任务提交流程:
提交任务
→ 核心线程未满?创建核心线程执行
→ 核心线程已满,队列未满?入队
→ 队列已满,最大线程未满?创建非核心线程执行
→ 最大线程已满?执行拒绝策略
四种拒绝策略:AbortPolicy(抛异常)、CallerRunsPolicy(调用者执行)、DiscardPolicy(丢弃)、DiscardOldestPolicy(丢弃队列最老任务)
1.4 JVM
Q:JVM 内存模型(运行时数据区)?
┌─────────────────────────────────────┐
│ 方法区(元空间) │ ← 类信息、常量、静态变量
│ Metaspace(JDK 8+) │
├─────────────────────────────────────┤
│ 堆 │ ← 对象实例、数组(GC 主要区域)
│ Heap │ 年轻代 + 老年代
├──────────────────┬──────────────────┤
│ 虚拟机栈 │ 本地方法栈 │ ← 方法调用、局部变量表
│ VM Stack │ Native Stack │
├──────────────────┴──────────────────┤
│ 程序计数器 │ ← 当前线程执行的字节码行号
│ Program Counter │
└─────────────────────────────────────┘
其中堆和方法区是所有线程共享的,虚拟机栈、本地方法栈、程序计数器是线程私有的。
Q:垃圾回收算法?
| 算法 | 原理 | 优缺点 |
|---|---|---|
| 标记-清除 | 标记存活对象,清除未标记的 | 简单,但产生内存碎片 |
| 标记-整理 | 标记后存活对象向一端移动 | 无碎片,但移动开销大 |
| 复制算法 | 将存活对象复制到另一半空间 | 无碎片,但浪费一半空间 |
常见垃圾收集器:
- CMS:以最短回收停顿为目标,标记-清除算法(老年代)
- G1:将堆划分为多个 Region,可预测停顿时间(JDK 9 默认)
- ZGC:超低停顿(< 1ms),JDK 11 引入,JDK 15 正式可用
二、数据库
2.1 MySQL 基础
Q:InnoDB 和 MyISAM 的区别?
| 对比项 | InnoDB | MyISAM |
|---|---|---|
| 事务 | 支持 | 不支持 |
| 锁粒度 | 行锁 | 表锁 |
| 外键 | 支持 | 不支持 |
| 崩溃恢复 | 支持(redo log) | 不支持 |
| 全文索引 | 支持但效果一般 | 支持 |
| MVCC | 支持 | 不支持 |
| count(*) | 不缓存,需遍历索引 | 缓存,速度快 |
| 默认引擎 | MySQL 5.5+ 默认 | 早期默认 |
Q:索引的类型?
- 主键索引:唯一且非空,一张表只能有一个
- 唯一索引:值唯一,允许 NULL
- 普通索引:最基本的索引,无限制
- 组合索引:多个列组合(遵循最左前缀匹配原则)
- 全文索引:用于文本搜索
Q:什么情况下索引会失效?
- 对索引列使用函数:
WHERE YEAR(create_time) = 2024 - 隐式类型转换:
WHERE phone = 13800138000(phone 是字符串类型) - 违反最左前缀原则:组合索引
(a, b, c),只查b, c - 使用
OR连接非索引列 LIKE以通配符开头:WHERE name LIKE '%abc'WHERE中对索引列做运算:WHERE id + 1 = 10- 优化器判断全表扫描更快时(如数据量极小或区分度极低)
Q:事务的四大特性(ACID)?
| 特性 | 含义 | 实现机制 |
|---|---|---|
| 原子性(Atomicity) | 事务是不可分割的最小操作单元 | undo log |
| 一致性(Consistency) | 数据从一个一致状态到另一个一致状态 | AID + 应用层约束 |
| 隔离性(Isolation) | 并发事务之间互不影响 | MVCC + 锁 |
| 持久性(Durability) | 事务提交后数据永久保存 | redo log |
Q:MySQL 的隔离级别?
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交(Read Uncommitted) | 有 | 有 | 有 |
| 读已提交(Read Committed) | 无 | 有 | 有 |
| 可重复读(Repeatable Read) | 无 | 无 | 有(InnoDB 通过 MVCC+间隙锁基本解决) |
| 串行化(Serializable) | 无 | 无 | 无 |
MySQL 默认隔离级别:可重复读(Repeatable Read)。
Q:MVCC 的原理?
MVCC(多版本并发控制)通过每行数据的隐藏列 + undo log 实现无锁读:
DB_TRX_ID:最近修改该行的事务 IDDB_ROLL_PTR:指向 undo log 中的旧版本DB_ROW_ID:隐藏主键
ReadView 判断版本可见性:
创建 ReadView 时记录:
m_ids:活跃事务 ID 列表
min_trx_id:最小活跃事务 ID
max_trx_id:下一个将分配的事务 ID
判断规则:
trx_id < min_trx_id → 可见(事务已提交)
trx_id >= max_trx_id → 不可见(事务在 ReadView 之后开始)
min_trx_id <= trx_id < max_trx_id → 不在 m_ids 中则可见
2.2 SQL 优化
Q:如何进行 SQL 优化?
- 通过
EXPLAIN查看执行计划,关注type、key、rows、Extra - 避免
SELECT *,只查需要的列 - 合理使用索引,避免索引失效
- 避免
IN子查询中的大量数据,可用JOIN替代 - 分页查询优化:大偏移量时用
WHERE id > last_id LIMIT n替代LIMIT offset, n - 避免在
WHERE中对列做函数运算
Q:EXPLAIN 中 type 字段的含义(从好到差)?
system > const > eq_ref > ref > range > index > ALL
const:主键或唯一索引等值查询,最多一条eq_ref:JOIN 时使用主键或唯一索引关联ref:普通索引等值查询range:索引范围扫描(BETWEEN、>、<)index:全索引扫描ALL:全表扫描(最差)
三、计算机网络
3.1 TCP/IP
Q:三次握手的过程?
客户端 服务器
│ │
│──── SYN(seq=x)─────────────>│ 第一次:客户端发送连接请求
│ │
│<─── SYN+ACK(seq=y,ack=x+1)──│ 第二次:服务器确认并发起连接
│ │
│──── ACK(ack=y+1)──────────>│ 第三次:客户端确认服务器的连接
│ │
│═══ 连接建立,开始传输数据 ═════│
为什么需要三次握手?
- 确认双方的发送和接收能力都正常
- 防止已失效的连接请求报文突然到达服务器,造成资源浪费
Q:四次挥手的过程?
客户端(主动关闭) 服务器(被动关闭)
│ │
│──── FIN(seq=u)─────────────>│ 第一次:客户端发送关闭请求
│ │
│<─── ACK(ack=u+1)────────────│ 第二次:服务器确认
│ │ (服务器仍可发送数据)
│ │
│ ... 服务器继续发送数据 ... │
│ │
│<─── FIN(seq=w)─────────────│ 第三次:服务器也发送关闭请求
│ │
│──── ACK(ack=w+1)──────────>│ 第四次:客户端确认
│ │
│ 等待 2MSL 后关闭 │
为什么需要四次挥手?
- TCP 是全双工的,每个方向都需要单独关闭
- 服务器收到 FIN 后可能还有数据未发送完,所以先回 ACK,等数据发完再发 FIN
Q:TIME_WAIT 状态的作用?
存在时间:2MSL(Maximum Segment Lifetime,约 1~4 分钟)
作用:
- 确保最后一个 ACK 能到达服务器(如果丢失,服务器会重发 FIN)
- 让本连接的所有报文在网络中消失,避免影响新连接
Q:TCP 如何保证可靠传输?
- 校验和:检测数据传输中的位错误
- 序列号:保证数据有序,接收方按序重组
- 确认应答(ACK):确认已收到的数据
- 超时重传:发送后未收到 ACK,在超时后重传
- 流量控制(滑动窗口):接收方通过窗口大小控制发送速率
- 拥塞控制(慢启动、拥塞避免、快速重传、快速恢复):防止网络过载
Q:拥塞控制和流量控制的区别?
| 对比项 | 流量控制 | 拥塞控制 |
|---|---|---|
| 目的 | 保护接收方不被淹没 | 防止网络过载 |
| 控制方 | 接收方(通过窗口大小) | 发送方(通过拥塞窗口) |
| 机制 | 滑动窗口 | 慢启动、拥塞避免等 |
3.2 HTTP
Q:HTTP 和 HTTPS 的区别?
| 对比项 | HTTP | HTTPS |
|---|---|---|
| 端口 | 80 | 443 |
| 安全性 | 明文传输 | TLS/SSL 加密传输 |
| 证书 | 不需要 | 需要 CA 证书 |
| 速度 | 略快 | 略慢(握手开销) |
Q:HTTP 常见状态码?
200 OK:请求成功301 Moved Permanently:永久重定向302 Found:临时重定向304 Not Modified:缓存未过期400 Bad Request:请求参数错误401 Unauthorized:未认证403 Forbidden:无权限404 Not Found:资源不存在500 Internal Server Error:服务器内部错误502 Bad Gateway:网关错误503 Service Unavailable:服务不可用
Q:GET 和 POST 的区别?
| 对比项 | GET | POST |
|---|---|---|
| 参数位置 | URL 中 | 请求体中 |
| 缓存 | 可被缓存 | 不可缓存 |
| 安全性 | 参数暴露在 URL | 参数在请求体,相对安全 |
| 参数长度 | 受 URL 长度限制 | 理论上无限制 |
| 幂等性 | 幂等 | 非幂等 |
| 浏览器回退 | 无害 | 会提示重新提交 |
Q:Cookie 和 Session 的区别?
| 对比项 | Cookie | Session |
|---|---|---|
| 存储位置 | 客户端浏览器 | 服务器端 |
| 大小限制 | 4KB 左右 | 无大小限制 |
| 安全性 | 可被篡改、窃取 | 相对安全 |
| 生命周期 | 可设置过期时间 | 默认浏览器关闭失效 |
| 跨域 | 同域下自动携带 | 通过 Cookie 中的 SessionID 关联 |
四、操作系统
Q:进程和线程的区别?
| 对比项 | 进程 | 线程 |
|---|---|---|
| 定义 | 资源分配的基本单位 | CPU 调度的基本单位 |
| 地址空间 | 独立 | 共享所属进程的地址空间 |
| 通信方式 | 管道、消息队列、共享内存等 | 共享内存(同一进程内) |
| 创建/切换开销 | 大 | 小 |
| 健壮性 | 一个进程崩溃不影响其他进程 | 一个线程崩溃可能导致整个进程崩溃 |
Q:进程间通信方式?
- 管道(Pipe):半双工,父子进程间使用
- 命名管道(FIFO):无亲缘关系的进程间通信
- 消息队列:消息链表,有格式的消息传递
- 共享内存:最快的方式,需要同步机制(信号量)
- 信号量(Semaphore):控制共享资源的访问
- 信号(Signal):异步通知,如
kill -9 - Socket:可用于不同主机间的通信
Q:死锁的四个必要条件?如何预防?
必要条件(同时满足才会死锁):
- 互斥:资源一次只能被一个进程使用
- 占有并等待:持有资源的同时等待其他资源
- 不可抢占:已获得的资源不能被强行夺走
- 循环等待:进程之间形成循环等待资源的关系
预防策略:
- 破坏互斥 → 难以实现(某些资源本身就是互斥的)
- 破坏占有并等待 → 一次性申请所有资源
- 破坏不可抢占 → 获取不到资源时主动释放已有资源
- 破坏循环等待 → 资源编号排序,按序申请
五、数据结构与算法
5.1 常见排序算法
| 算法 | 平均时间 | 最坏时间 | 空间 | 稳定性 |
|---|---|---|---|---|
| 冒泡排序 | O(n²) | O(n²) | O(1) | 稳定 |
| 选择排序 | O(n²) | O(n²) | O(1) | 不稳定 |
| 插入排序 | O(n²) | O(n²) | O(1) | 稳定 |
| 快速排序 | O(n log n) | O(n²) | O(log n) | 不稳定 |
| 归并排序 | O(n log n) | O(n log n) | O(n) | 稳定 |
| 堆排序 | O(n log n) | O(n log n) | O(1) | 不稳定 |
面试高频:手写快排
public void quickSort(int[] arr, int left, int right) {
if (left >= right) return;
int pivot = partition(arr, left, right);
quickSort(arr, left, pivot - 1);
quickSort(arr, pivot + 1, right);
}
private int partition(int[] arr, int left, int right) {
int pivot = arr[right];
int i = left;
for (int j = left; j < right; j++) {
if (arr[j] < pivot) {
swap(arr, i, j);
i++;
}
}
swap(arr, i, right);
return i;
}
5.2 常考算法题型
| 题型 | 代表题目 | 关键思路 |
|---|---|---|
| 二分查找 | 在有序数组中查找目标值 | 左闭右开区间,注意边界条件 |
| 链表 | 反转链表、判断环、合并有序链表 | 虚拟头节点、快慢指针 |
| 二叉树 | 前中后序遍历、层序遍历、最近公共祖先 | 递归、BFS/DFS |
| 动态规划 | 最长子序列、背包问题、爬楼梯 | 定义 dp 数组、找状态转移方程 |
| 滑动窗口 | 最长无重复子串、最小覆盖子串 | 双指针维护窗口 |
| 回溯 | 全排列、组合、N 皇后 | 做选择 → 递归 → 撤销选择 |
5.3 时间复杂度速记
O(1) < O(log n) < O(n) < O(n log n)
常数时间 对数时间 线性时间 线性对数
O(n²) < O(n³) < O(2ⁿ) < O(n!)
平方时间 立方时间 指数时间 阶乘时间
六、Spring 框架
Q:Spring IoC 的原理?
IoC(控制反转)将对象的创建和管理从代码内部转移到 Spring 容器。
- BeanFactory:基础容器,懒加载
- ApplicationContext:扩展容器,启动时预加载所有 Bean
Bean 的生命周期:
实例化 → 属性注入(依赖注入)→ Aware 接口回调
→ BeanNameAware / BeanFactoryAware
→ BeanPostProcessor.postProcessBeforeInitialization
→ InitializingBean.afterPropertiesSet
→ 自定义 init-method
→ BeanPostProcessor.postProcessAfterInitialization
→ 使用
→ DisposableBean.destroy / 自定义 destroy-method
Q:Spring AOP 的原理?
AOP(面向切面编程)将横切逻辑(日志、事务、权限)从业务代码中分离。
实现方式:
- JDK 动态代理:基于接口,使用
Proxy.newProxyInstance(),目标类必须实现接口 - CGLIB 代理:基于继承,生成目标类的子类,不能代理 final 方法
Spring 默认策略:有接口用 JDK 代理,无接口用 CGLIB 代理。
Q:Spring 事务 @Transactional 在什么情况下会失效?
- 方法不是
public的 - 方法是
final或static的 - 同一个类中方法内部调用(未经过代理)
- 异常被 catch 吞掉,未重新抛出
- 抛出了非
RuntimeException(默认只回滚 RuntimeException 和 Error) - 数据库引擎不支持事务(如 MyISAM)
Q:Spring Boot 自动装配的原理?
核心注解 @SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan
@EnableAutoConfiguration
→ @Import(AutoConfigurationImportSelector.class)
→ 读取 META-INF/spring.factories(Spring Boot 2.x)
或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 3.x)
→ 加载自动配置类
→ 根据 @Conditional 系列注解判断是否生效
→ @ConditionalOnClass(类路径存在某类)
→ @ConditionalOnProperty(配置文件存在某属性)
→ @ConditionalOnMissingBean(容器中不存在某 Bean)
七、Redis
Q:Redis 常见的数据结构?
| 数据类型 | 底层实现 | 常见应用场景 |
|---|---|---|
| String | SDS(Simple Dynamic String) | 缓存、计数器、分布式锁 |
| Hash | 哈希表 + 压缩列表 | 存储对象、购物车 |
| List | 双向链表 + 压缩列表 | 消息队列、最新列表 |
| Set | 哈希表 | 去重、标签、共同好友 |
| ZSet | 跳表 + 哈希表 | 排行榜、延时队列 |
Q:Redis 的持久化机制?
| 方式 | RDB(快照) | AOF(追加日志) |
|---|---|---|
| 原理 | 定时将内存数据快照写入磁盘 | 记录每次写操作命令 |
| 文件 | dump.rdb | appendonly.aof |
| 恢复速度 | 快(直接加载文件) | 慢(重放所有命令) |
| 数据安全性 | 可能丢失最后一次快照后的数据 | 更安全(每秒刷盘最多丢 1 秒) |
| 文件大小 | 小(二进制压缩) | 大 |
| 适用场景 | 备份、灾难恢复 | 数据安全要求高的场景 |
Q:缓存穿透、缓存击穿、缓存雪崩的区别和解决方案?
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 缓存穿透 | 查询不存在的数据,缓存和数据库都没有 | 布隆过滤器、缓存空值、参数校验 |
| 缓存击穿 | 热点 Key 过期,大量请求打到数据库 | 互斥锁、热点数据永不过期(逻辑过期) |
| 缓存雪崩 | 大量 Key 同时过期,或 Redis 宕机 | 过期时间加随机值、搭建高可用集群、限流降级 |
Q:Redis 如何实现分布式锁?
# 加锁(SETNX + 过期时间,保证原子性)
SET lock_key unique_value NX PX 30000
# 释放锁(Lua 脚本,保证原子性)
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
关键点:必须设置过期时间(防止死锁)、释放时校验值(防止误删)、使用 Lua 脚本保证原子性。
更完善的方案:Redisson(看门狗机制自动续期)。
八、常见设计题
8.1 手写代码题
反转单链表
public ListNode reverseList(ListNode head) {
ListNode prev = null, curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
LRU 缓存
class LRUCache {
private int capacity;
private Map<Integer, Node> map;
private Node head, tail; // 双向链表的头尾哨兵
public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap<>();
head = new Node(); tail = new Node();
head.next = tail; tail.prev = head;
}
public int get(int key) {
if (!map.containsKey(key)) return -1;
Node node = map.get(key);
removeToHead(node); // 移到链表头部
return node.val;
}
public void put(int key, int value) {
if (map.containsKey(key)) {
map.get(key).val = value;
removeToHead(map.get(key));
} else {
if (map.size() >= capacity) {
map.remove(tail.prev.key); // 移除链表尾部
removeNode(tail.prev);
}
Node node = new Node(key, value);
map.put(key, node);
addToHead(node);
}
}
}
8.2 场景设计题
Q:设计一个短链服务?
核心思路:长 URL → 哈希/发号器 → 短码 → 存数据库 → 重定向
长 URL → MD5(长URL) → 取前 6~8 位作为短码(处理冲突)
或发号器自增 ID → Base62 编码 → 短码
存储:短码 → 长URL 的映射(数据库 + 缓存)
访问:短码 → 查缓存 → 查数据库 → 302 重定向到长 URL
Q:如何设计一个秒杀系统?
核心挑战:短时间内大量请求,库存有限。
前端:按钮防重复点击、验证码、请求限流
网关:令牌桶限流
缓存层:
- 库存预扣减(Redis DECR)
- 用户去重(SET 防止重复下单)
消息队列:
- 削峰填谷,将请求异步化
- 下单请求进入 MQ,消费者依次处理
数据库:
- 订单表:最终一致性
- 库存表:乐观锁(UPDATE stock SET count = count - 1 WHERE id = ? AND count > 0)
九、面试软技能
9.1 自我介绍模板
面试官您好,我是 XX 学校计算机专业的应届毕业生。在校期间我主要学习了 Java 后端开发,熟悉 Spring Boot、MySQL、Redis 等技术栈。实习期间在 XX 公司负责 XX 模块的开发,使用了 XX 技术解决了 XX 问题。我的毕业设计是 XX,主要实现了 XX 功能。我对技术有持续的热情,希望能加入贵公司。
关键点:控制在 2 分钟以内,突出项目经验和技术亮点。
9.2 常见 HR 问题
| 问题 | 回答要点 |
|---|---|
| 你的优缺点? | 优点结合技术能力,缺点说真实但可控的(如"有时过于关注细节") |
| 为什么选择我们公司? | 结合公司业务和自身职业规划 |
| 你的职业规划? | 1~3 年深耕技术,3~5 年向架构/技术管理发展 |
| 最大的挑战/收获? | 具体项目场景 + 解决过程 + 反思总结 |
| 你有什么问题想问? | 问团队技术栈、工作流程、新人培养机制 |
十、总结
应届生面试的知识图谱:
计算机基础
├── Java 基础
│ ├── 集合框架(HashMap、ConcurrentHashMap)
│ ├── 多线程(synchronized、volatile、线程池)
│ └── JVM(内存模型、GC 算法)
├── 数据库
│ ├── MySQL(索引、事务、MVCC)
│ └── SQL 优化(EXPLAIN)
├── 计算机网络
│ ├── TCP/UDP(三次握手、四次挥手)
│ └── HTTP/HTTPS(状态码、缓存)
├── 操作系统
│ ├── 进程与线程
│ └── 死锁
├── 数据结构与算法
│ ├── 排序算法
│ ├── 链表、二叉树
│ └── 动态规划、滑动窗口
├── 框架
│ ├── Spring(IoC、AOP、事务)
│ └── Spring Boot(自动装配)
├── Redis
│ ├── 数据结构
│ ├── 持久化
│ └── 缓存问题(穿透、击穿、雪崩)
└── 设计题
├── 手写代码(链表、LRU)
└── 场景设计(短链、秒杀)
建议按广度优先的策略准备,先覆盖所有常见知识点,再对高频考点深入理解。刷 LeetCode 时重点攻克链表、二叉树、动态规划三大类。
991

被折叠的 条评论
为什么被折叠?



