Java后端开发实习生面试题及回答详解
Java后端开发实习生面试题及回答详解
小葱Java后端开发实习生面试题及回答详解
目录
Java基础
Q1: Java的特点是什么?
回答要点:
- 面向对象:封装、继承、多态
- 平台无关性:一次编写,到处运行(JVM)
- 自动内存管理:垃圾回收机制
- 多线程支持:内置多线程机制
- 安全性:字节码验证、安全管理器
- 健壮性:异常处理机制
示例回答:
Java是一门面向对象的编程语言,具有平台无关性,通过JVM实现"一次编写,到处运行"。 |
Q2: Java的基本数据类型有哪些?它们占用的字节数是多少?
回答要点:
| 数据类型 | 字节数 | 取值范围 | 默认值 |
|---|---|---|---|
| byte | 1 | -128 ~ 127 | 0 |
| short | 2 | -2^15 ~ 2^15-1 | 0 |
| int | 4 | -2^31 ~ 2^31-1 | 0 |
| long | 8 | -2^63 ~ 2^63-1 | 0L |
| float | 4 | IEEE 754 | 0.0f |
| double | 8 | IEEE 754 | 0.0d |
| char | 2 | 0 ~ 65535 | ‘\u0000’ |
| boolean | 1位 | true/false | false |
记忆技巧:
- 整数类型:byte(1) < short(2) < int(4) < long(8)
- 浮点类型:float(4) < double(8)
- char是2字节(Unicode字符)
Q3: == 和 equals() 的区别?
回答要点:
// == 比较的是引用地址 |
核心区别:
==:比较基本数据类型时比较值,比较引用类型时比较内存地址equals():Object类中默认比较地址,但很多类(如String、Integer)重写了equals方法,比较内容
面试加分点:
// 重写equals()的规范 |
Q4: String、StringBuilder、StringBuffer的区别?
回答要点:
| 类 | 可变性 | 线程安全 | 性能 | 使用场景 |
|---|---|---|---|---|
| String | 不可变 | 安全 | 慢(频繁拼接) | 字符串常量 |
| StringBuilder | 可变 | 不安全 | 快 | 单线程字符串拼接 |
| StringBuffer | 可变 | 安全(synchronized) | 中等 | 多线程字符串拼接 |
代码示例:
// String - 不可变,每次拼接都创建新对象 |
Q5: final关键字的作用?
回答要点:
修饰变量:变量只能赋值一次,成为常量
final int x = 10;
// x = 20; // 编译错误修饰方法:方法不能被重写
class Parent {
final void method() { } // 子类不能重写
}修饰类:类不能被继承
final class MyClass { } // 不能被继承
// class Child extends MyClass { } // 编译错误
面试加分点:
final修饰引用类型时,引用不能改变,但对象内容可以改变
final List<String> list = new ArrayList<>();
list.add("hello"); // 可以
// list = new ArrayList<>(); // 编译错误
面向对象编程
Q6: 面向对象的三大特性是什么?请详细说明。
回答要点:
1. 封装(Encapsulation)
- 定义:隐藏对象的内部实现细节,只暴露必要的接口
- 好处:提高代码安全性、可维护性
- 实现:使用private修饰属性,提供getter/setter方法
public class Student { |
2. 继承(Inheritance)
- 定义:子类继承父类的属性和方法
- 好处:代码复用,提高可维护性
- 特点:Java单继承,但可以实现多个接口
class Animal { |
3. 多态(Polymorphism)
- 定义:同一接口的不同实现
- 实现方式:方法重写、方法重载、接口实现
- 运行时多态:通过方法重写实现
class Animal { |
Q7: 抽象类和接口的区别?
回答要点:
| 特性 | 抽象类 | 接口 |
|---|---|---|
| 关键字 | abstract class | interface |
| 继承/实现 | extends | implements |
| 方法 | 可以有抽象方法和具体方法 | Java 8前只能有抽象方法 |
| 变量 | 可以有普通变量 | 只能是public static final |
| 构造方法 | 可以有 | 不能有 |
| 继承 | 单继承 | 可以实现多个接口 |
| 访问修饰符 | 任意 | public(默认) |
代码示例:
// 抽象类 |
使用场景:
- 抽象类:有共同属性和行为的类,需要构造方法
- 接口:定义规范,实现多继承效果
Q8: 重写(Override)和重载(Overload)的区别?
回答要点:
| 特性 | 重写(Override) | 重载(Overload) |
|---|---|---|
| 定义 | 子类重写父类方法 | 同一类中方法名相同,参数不同 |
| 方法名 | 必须相同 | 必须相同 |
| 参数列表 | 必须相同 | 必须不同 |
| 返回类型 | 相同或子类 | 可以不同 |
| 访问修饰符 | 不能更严格 | 可以不同 |
| 异常 | 不能抛出更广泛的异常 | 可以不同 |
| 发生位置 | 父子类之间 | 同一类中 |
代码示例:
class Parent { |
集合框架
Q9: 请介绍Java集合框架的体系结构?
回答要点:
Collection(接口) |
Q10: ArrayList和LinkedList的区别?
回答要点:
| 特性 | ArrayList | LinkedList |
|---|---|---|
| 底层结构 | 动态数组 | 双向链表 |
| 随机访问 | O(1) | O(n) |
| 插入/删除 | O(n) | O(1)(已知位置) |
| 内存占用 | 连续内存 | 分散内存(指针开销) |
| 适用场景 | 频繁查询 | 频繁插入删除 |
代码示例:
// ArrayList - 适合查询 |
Q11: HashMap的底层原理?
回答要点:
JDK 1.8之前
- 结构:数组 + 链表
- 哈希冲突:使用链表解决
- 问题:链表过长时查询效率低
JDK 1.8之后
- 结构:数组 + 链表 + 红黑树
- 优化:链表长度 > 8 时转换为红黑树
- 扩容:负载因子0.75,容量2倍扩容
核心机制:
// 1. 计算hash值 |
面试加分点:
// 为什么容量是2的幂次? |
Q12: HashMap和Hashtable的区别?
回答要点:
| 特性 | HashMap | Hashtable |
|---|---|---|
| 线程安全 | 不安全 | 安全(synchronized) |
| null值 | 允许一个null key,多个null value | 不允许null |
| 效率 | 高 | 低(同步开销) |
| 继承 | AbstractMap | Dictionary |
| 迭代器 | Fail-Fast | Fail-Safe |
| 版本 | JDK 1.2+ | JDK 1.0(已过时) |
推荐使用:
- 单线程:
HashMap - 多线程:
ConcurrentHashMap(推荐)或Hashtable
Q13: HashSet的底层实现原理?
回答要点:
// HashSet底层使用HashMap实现 |
特点:
- 使用HashMap的key存储元素
- value统一为PRESENT常量
- 因此HashSet的特性与HashMap的key特性一致
多线程与并发
Q14: 创建线程的方式有哪些?
回答要点:
方式1:继承Thread类
class MyThread extends Thread { |
方式2:实现Runnable接口(推荐)
class MyRunnable implements Runnable { |
方式3:实现Callable接口(有返回值)
class MyCallable implements Callable<String> { |
方式4:线程池(实际开发推荐)
ExecutorService executor = Executors.newFixedThreadPool(5); |
推荐使用Runnable的原因:
- Java单继承,继承Thread后无法继承其他类
- Runnable更灵活,可以传入线程池
- 符合面向接口编程原则
Q15: 线程的生命周期(状态)?
回答要点:
NEW(新建) |
Java中的6种状态(Thread.State):
public enum State { |
Q16: sleep()和wait()的区别?
回答要点:
| 特性 | sleep() | wait() |
|---|---|---|
| 所属类 | Thread | Object |
| 释放锁 | 不释放 | 释放 |
| 使用位置 | 任何地方 | 同步代码块/方法中 |
| 唤醒方式 | 时间到自动唤醒 | notify()/notifyAll() |
| 异常 | InterruptedException | InterruptedException |
代码示例:
// sleep() - 不释放锁 |
Q17: synchronized关键字的作用?
回答要点:
1. 修饰实例方法
public synchronized void method() { |
2. 修饰静态方法
public static synchronized void method() { |
3. 修饰代码块
synchronized (obj) { |
原理:
- JVM层面:通过monitorenter和monitorexit指令实现
- 对象头:每个对象都有monitor(监视器锁)
- 可重入:同一线程可以多次获取同一把锁
面试加分点:
// synchronized的优化(JDK 1.6+) |
Q18: volatile关键字的作用?
回答要点:
1. 保证可见性
// 不使用volatile |
2. 禁止指令重排序
// 双重检查锁定单例模式 |
注意:volatile不保证原子性
volatile int count = 0; |
Q19: 线程池的核心参数有哪些?
回答要点:
ThreadPoolExecutor( |
执行流程:
任务提交 |
拒绝策略:
AbortPolicy:抛出异常(默认)CallerRunsPolicy:调用者线程执行DiscardPolicy:直接丢弃DiscardOldestPolicy:丢弃最旧的任务
JVM内存管理
Q20: JVM内存区域划分?
回答要点:
JVM内存区域 |
各区域说明:
- 程序计数器:记录当前执行的字节码指令地址
- 虚拟机栈:存储局部变量、方法参数、返回地址
- 本地方法栈:为Native方法服务
- 堆:存放对象实例,GC主要区域
- 方法区:存储类信息、常量、静态变量(JDK 8后改为Metaspace)
Q21: 垃圾回收算法有哪些?
回答要点:
1. 标记-清除(Mark-Sweep)
- 过程:标记需要回收的对象,然后清除
- 缺点:产生内存碎片
2. 复制算法(Copying)
- 过程:将存活对象复制到另一块内存
- 适用:新生代(Eden和Survivor)
- 缺点:内存利用率低
3. 标记-整理(Mark-Compact)
- 过程:标记后,将存活对象向一端移动
- 适用:老年代
- 优点:无碎片
4. 分代收集(Generational)
- 新生代:复制算法(Minor GC)
- 老年代:标记-清除/标记-整理(Major GC / Full GC)
Q22: 常见的垃圾收集器有哪些?
回答要点:
| 收集器 | 区域 | 算法 | 特点 |
|---|---|---|---|
| Serial | 新生代 | 复制 | 单线程,STW |
| ParNew | 新生代 | 复制 | Serial的多线程版 |
| Parallel Scavenge | 新生代 | 复制 | 吞吐量优先 |
| Serial Old | 老年代 | 标记-整理 | Serial的老年代版 |
| Parallel Old | 老年代 | 标记-整理 | Parallel Scavenge的老年代版 |
| CMS | 老年代 | 标记-清除 | 并发收集,低延迟 |
| G1 | 全堆 | 标记-整理+复制 | 可预测停顿时间 |
| ZGC | 全堆 | 标记-整理 | 超低延迟(JDK 11+) |
常用组合:
- ParNew + CMS:低延迟
- Parallel Scavenge + Parallel Old:高吞吐量
- G1:平衡(JDK 9默认)
数据库相关
Q23: SQL的几种连接方式?
回答要点:
-- 内连接(INNER JOIN):只返回两表都有的记录 |
Q24: 数据库事务的ACID特性?
回答要点:
- Atomicity(原子性):事务要么全部成功,要么全部失败
- Consistency(一致性):事务前后数据保持一致
- Isolation(隔离性):并发事务之间相互隔离
- Durability(持久性):事务提交后数据永久保存
隔离级别:
- READ UNCOMMITTED:读未提交(最低)
- READ COMMITTED:读已提交(Oracle默认)
- REPEATABLE READ:可重复读(MySQL默认)
- SERIALIZABLE:串行化(最高)
Q25: 数据库索引的作用和原理?
回答要点:
作用:
- 加快查询速度
- 保证数据唯一性(唯一索引)
- 加速表连接
原理:
- B+树:MySQL InnoDB默认索引结构
- 哈希索引:Memory引擎使用
索引类型:
- 主键索引:PRIMARY KEY
- 唯一索引:UNIQUE
- 普通索引:INDEX
- 组合索引:多个字段组合
注意事项:
- 索引不是越多越好(影响写入性能)
- 避免在WHERE子句中使用函数
- 最左前缀原则
Spring框架
Q26: Spring的IoC和DI是什么?
回答要点:
IoC(Inversion of Control,控制反转):
- 传统方式:对象自己创建依赖
- IoC方式:由容器创建和管理对象
- 好处:降低耦合,提高灵活性
DI(Dependency Injection,依赖注入):
- IoC的实现方式
- 通过构造函数、setter方法、接口注入依赖
代码示例:
// 传统方式(紧耦合) |
Q27: Spring Bean的作用域有哪些?
回答要点:
| 作用域 | 说明 | 使用场景 |
|---|---|---|
| singleton | 单例(默认) | 无状态Bean |
| prototype | 多例 | 有状态Bean |
| request | 每个HTTP请求一个实例 | Web应用 |
| session | 每个HTTP Session一个实例 | Web应用 |
| application | 每个ServletContext一个实例 | Web应用 |
代码示例:
|
Q28: Spring AOP是什么?有哪些应用场景?
回答要点:
AOP(Aspect-Oriented Programming,面向切面编程):
- 将横切关注点(日志、事务、安全等)从业务逻辑中分离
- 通过代理模式实现
核心概念:
- Aspect(切面):横切关注点的模块化
- Join Point(连接点):方法执行点
- Pointcut(切点):匹配连接点的表达式
- Advice(通知):在切点执行的动作
- Target(目标对象):被代理的对象
应用场景:
- 日志记录
- 事务管理
- 权限控制
- 性能监控
- 异常处理
代码示例:
|
Q29: Spring MVC的工作流程?
回答要点:
1. 用户请求 → DispatcherServlet(前端控制器) |
核心组件:
- DispatcherServlet:前端控制器
- HandlerMapping:映射请求到处理器
- HandlerAdapter:调用处理器
- ViewResolver:解析视图
- Controller:处理业务逻辑
项目经验与场景题
Q30: 请介绍一下你做的项目?
回答模板:
项目背景: |
示例回答:
我参与开发了一个在线图书管理系统,主要负责后端开发,项目周期3个月。 |
Q31: 如何解决高并发问题?
回答要点:
1. 缓存
- Redis缓存热点数据
- 减少数据库压力
2. 消息队列
- 异步处理,削峰填谷
- RabbitMQ、Kafka等
3. 数据库优化
- 读写分离
- 分库分表
- 索引优化
4. 限流
- 令牌桶、漏桶算法
- 使用Guava RateLimiter或Sentinel
5. 分布式锁
- Redis分布式锁
- Zookeeper分布式锁
6. CDN
- 静态资源CDN加速
Q32: 如何保证接口的幂等性?
回答要点:
幂等性:同一请求执行多次,结果相同
实现方式:
1. 唯一索引
-- 数据库唯一索引防止重复插入 |
2. 分布式锁
String lockKey = "order:" + orderNo; |
3. Token机制
// 1. 生成token,存入Redis |
4. 状态机
- 通过状态流转保证幂等性
算法与数据结构
Q33: 常见的排序算法及其时间复杂度?
回答要点:
| 算法 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 |
|---|---|---|---|---|
| 冒泡排序 | 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) { |
Q34: 如何判断链表是否有环?
回答要点:
方法1:快慢指针(Floyd判圈算法)
public boolean hasCycle(ListNode head) { |
方法2:HashSet
public boolean hasCycle(ListNode head) { |
其他技术栈
Q35: Redis的常用数据类型?
回答要点:
| 类型 | 说明 | 应用场景 |
|---|---|---|
| String | 字符串 | 缓存、计数器 |
| Hash | 哈希表 | 存储对象 |
| List | 列表 | 消息队列、最新列表 |
| Set | 集合 | 去重、交集并集 |
| Sorted Set | 有序集合 | 排行榜 |
| Bitmap | 位图 | 签到、布隆过滤器 |
| HyperLogLog | 基数统计 | UV统计 |
Q36: HTTP和HTTPS的区别?
回答要点:
| 特性 | HTTP | HTTPS |
|---|---|---|
| 端口 | 80 | 443 |
| 安全性 | 明文传输 | 加密传输 |
| 证书 | 不需要 | 需要SSL证书 |
| 性能 | 快 | 稍慢(加密开销) |
| SEO | 一般 | 更好 |
HTTPS工作原理:
- 客户端请求HTTPS连接
- 服务器返回SSL证书
- 客户端验证证书
- 双方协商加密算法和密钥
- 使用对称加密传输数据
Q37: RESTful API设计原则?
回答要点:
- 资源:使用名词,如
/users、/orders - HTTP方法:
- GET:查询
- POST:创建
- PUT:更新(完整)
- PATCH:更新(部分)
- DELETE:删除
- 状态码:200、201、400、404、500等
- 版本控制:
/api/v1/users - 过滤和分页:
/users?page=1&size=10
示例:
GET /api/v1/users # 获取用户列表 |
面试技巧总结
回答问题的STAR法则
- S(Situation):情境
- T(Task):任务
- A(Action):行动
- R(Result):结果
常见问题准备
自我介绍(1-2分钟)
- 姓名、学校、专业
- 技术栈和项目经验
- 为什么选择这个岗位
为什么选择我们公司?
- 了解公司业务和技术
- 表达对岗位的兴趣
- 展示学习意愿
你的优缺点?
- 优点:结合技术能力
- 缺点:说可以改进的,并说明改进计划
职业规划?
- 短期:快速成长,掌握核心技术
- 长期:成为技术专家或架构师
技术问题回答技巧
- 先回答核心概念
- 举例说明
- 对比其他方案
- 结合实际项目经验
注意事项
- 诚实:不会的就说不会,但可以表达学习意愿
- 自信:保持自信但不要自负
- 沟通:思路清晰,表达流畅
- 准备:提前了解公司和岗位要求
推荐学习资源
书籍
- 《Java核心技术》
- 《深入理解Java虚拟机》
- 《Spring实战》
- 《Redis设计与实现》
在线资源
- Java官方文档
- Spring官方文档
- 牛客网、LeetCode(算法练习)
- GitHub(开源项目学习)
实践项目
- 个人博客系统
- 在线商城
- 图书管理系统
- 在线聊天系统
祝面试顺利!记住:准备充分,自信表达,诚实回答!
