2026 Java后端面试题总结(持续更新):Spring、MyBatis、Redis、MySQL、多线程

1. ==和equals的区别?

面试版:

== 比较引用是否相同,equals 比较内容是否相等
真正理解版:

== 比较是不是同一个对象;equals 比较这个类定义的"相等规则"

2. 说一下HashMap的底层原理

数组:找到大概位置

链表:解决多个数据撞到同一个位置

红黑树:解决链表太长导致查询慢

3. 说一下ArrayList和LinkedList的区别

数组擅长找位置,链表擅长改连接。

ArrayList 底层基于动态数组实现,查询通过下标直接定位,时间复杂度 O(1),但是中间插入删除需要移动元素,效率较低。LinkedList 底层基于双向链表实现,插入删除只需要修改指针,效率较高,但是查询需要遍历,时间复杂度 O(n)。另外 LinkedList 每个节点需要保存前后指针,所以占用内存更多。实际开发中查询和遍历较多一般选择 ArrayList。

4. 怎么搭建一个springboot项目?还有你们用的springboot的版本是什么?

我们项目一般通过 Spring Initializr 创建 Spring Boot 项目,选择 Maven 管理依赖,引入 Spring Web、MyBatis、数据库驱动等依赖。项目启动类使用 @SpringBootApplication 注解,通过 SpringApplication.run 启动 Spring 容器。配置文件使用 application.yml 管理端口、数据库等配置。

我们项目目前使用 Spring Boot 2.7.x(或者3.x,根据实际情况),配合 JDK 8/17,主要使用 Spring MVC、MyBatis、MySQL 等技术。

5. @RestController和@Controller的区别

@Controller 是 Spring MVC 中用于处理页面请求的控制器,方法返回值默认会被视图解析器解析成页面。@RestController 是 Spring 4 提供的注解,本质上等于 @Controller 加 @ResponseBody,返回值会直接写入 HTTP 响应,通常返回 JSON 数据,用于开发 RESTful 接口

6. 什么是IOC?什么是DI?

IOC(控制反转)是指把对象的创建和管理交给 Spring 容器,而不是由代码主动创建。DI(依赖注入)是 IOC 的具体实现方式,Spring 容器创建 Bean 后,通过构造方法、Setter 或字段方式,把对象依赖注入到需要它的类中。简单来说,IOC 解决对象由谁创建,DI 解决对象如何传递。

7. @Autowired和@Resource的区别

@Autowired 是 Spring 提供的注解,默认按照类型进行依赖注入,如果存在多个相同类型的 Bean,需要配合 @Qualifier 指定 Bean 名称。@Resource 是 Java 提供的注解,默认按照名称注入,如果名称找不到再按照类型匹配。实际 Spring Boot 开发中两者都可以使用,现在更推荐使用构造方法注入。

8. get请求和post请求的区别

GET主要用于获取资源,POST主要用于提交数据。

ET 和 POST 都是 HTTP 请求方法。GET 主要用于获取资源,请求参数通常放在 URL 中,具有幂等性,适合查询。POST 主要用于提交数据,请求参数通常放在请求体中,常用于新增、修改操作。两者安全性主要取决于 HTTPS,而不是 GET 或 POST 本身。

9. 你说一下过滤器和拦截器的区别

过滤器(Filter)是 Servlet 层面的,拦截器(Interceptor)是 Spring MVC 层面的。

Filter 和 Interceptor 都可以实现请求拦截,但是作用层级不同。Filter 属于 Servlet 规范,在请求进入 Spring MVC 之前执行,能处理所有请求,但是不知道具体 Controller 信息。Interceptor 属于 Spring MVC,在 DispatcherServlet 之后、Controller 执行之前执行,可以获取 Handler 信息,更适合做登录认证和权限控制。执行顺序上 Filter 比 Interceptor 更早。

10. 你们公司是怎么管理分支的?遇到代码冲突怎么解决?

们项目一般采用 Git 分支管理,比如 master/main 作为生产分支,develop 作为开发分支,每个需求创建独立 feature 分支。开发完成后提交 Merge Request,由其他成员 Code Review 后合并。遇到代码冲突时,首先通过 git status 查看冲突文件,然后手动比较双方修改,根据业务保留或合并代码,解决后 git add 和 git commit 完成合并。平时通过及时拉取最新代码、小功能提交来减少冲突。

11. 你们是怎么保存用户登录信息的?你们的jwt需要在服务端存储吗?说一下jwt的组成部分有哪些?如何防篡改?

我们用户登录成功后,服务端生成 JWT Token 返回客户端,客户端保存 Token,后续请求通过 Authorization Header 携带 Token。JWT 本身是无状态认证,正常情况下服务端不需要保存 Token,服务端通过签名校验 Token 是否被篡改。JWT 由 Header、Payload、Signature 三部分组成,Header 保存算法信息,Payload 保存用户信息和过期时间,Signature 用密钥对前两部分签名,防止数据被修改。如果需要实现主动注销、踢下线等功能,可以在 Redis 中保存 Token 黑名单或者维护 Token 状态。

12. 你们项目是怎么处理异常的?你说一下怎么实现全局自定义异常处理器?

我们项目使用 Spring Boot 的全局异常处理机制统一处理异常,通过 @RestControllerAdvice 创建全局异常处理类,通过 @ExceptionHandler 捕获不同类型异常。业务异常会自定义 BusinessException,在 Service 层发现业务问题时主动抛出,由全局处理器转换成统一响应格式返回给前端。同时会区分业务异常、参数校验异常和系统异常,避免 Controller 中大量 try-catch,提高代码可维护性。

13. 内连接和外连接有什么区别?

内连接 INNER JOIN 是返回两个表中满足连接条件的数据,只返回匹配成功的记录。外连接分为左外连接和右外连接,左连接保留左表全部数据,右表没有匹配时显示 NULL;右连接反之。实际开发中左连接使用比较多,例如查询所有用户以及用户对应的数据,即使用户没有相关记录也需要展示。

LEFT JOIN 后面 WHERE 条件写错,会变成 INNER JOIN。

14. char和varchar的区别

CHAR 和 VARCHAR 都是 MySQL 中存储字符串的数据类型。CHAR 是固定长度类型,创建时指定长度,存储不足会使用空格填充,适合存储长度固定的数据,例如手机号、身份证号。VARCHAR 是可变长度类型,只保存实际数据长度,节省空间,适合用户名、地址等长度不固定的数据。实际开发中 VARCHAR 使用更多。

15. 什么是事务?你说一下事务有哪些特性?

事务是一组数据库操作的集合,这些操作要么全部成功,要么全部失败,通过事务可以保证数据的一致性。事务具有 ACID 四个特性:原子性表示事务不可分割,要么成功要么失败;一致性表示事务执行前后数据保持正确状态;隔离性表示多个事务并发执行时互不影响;持久性表示事务提交后的数据会永久保存。

16. mybatis的#和$的区别

#{} 是预编译参数,占位符替换,安全;${} 是字符串直接拼接,有 SQL 注入风险

MyBatis 中 #{} 和 KaTeX parse error: Expected 'EOF', got '#' at position 21: ...以传递参数,但是实现方式不同。#̲{} 使用预编译方式,通过 P...{} 是直接字符串替换,会把参数拼接到 SQL 中,存在 SQL 注入风险,一般只用于动态表名、字段名等场景,并且需要严格校验参数来源。

17. mybatis的接口方法支持重载吗?为什么?

MyBatis 的 Mapper 接口方法不支持重载。

MyBatis 的 Mapper 接口方法不支持重载。虽然 Java 方法支持重载,但是 MyBatis 是通过 Mapper 的 namespace 加方法名 id 来绑定 SQL 的,并不会根据参数列表区分方法。如果出现同名方法,会导致 SQL 映射冲突。因此 Mapper 接口中的方法名必须唯一。

18. 你在项目中有使用过多线程吗?

项目中使用过多线程,主要用于处理一些耗时任务,例如文件上传、图片处理、异步通知等,避免阻塞主业务流程。在 Spring Boot 中通常使用线程池或者 @Async 实现异步处理,而不是直接创建 Thread。使用多线程时需要注意线程安全问题,比如多个线程同时修改共享变量可能导致数据不一致,可以通过 synchronized、Lock 或线程安全集合等方式解决。

19. 线程池的作用是什么?

线程池的作用是管理线程,减少线程创建和销毁的开销,提高系统性能,并控制并发数量。

线程池主要用于管理线程,避免频繁创建和销毁线程带来的性能开销。它可以复用线程,提高系统响应速度,同时通过限制线程数量控制并发,避免大量线程导致系统资源耗尽。在项目中通常使用 ThreadPoolExecutor 或 Spring 的线程池处理异步任务,例如消息发送、文件处理、数据同步等。

20. 线程池有哪些核心参数?

线程池核心参数决定了:创建多少线程、任务怎么排队、线程什么时候回收、任务满了怎么办。

ThreadPoolExecutor 有 7 个核心参数:corePoolSize 表示核心线程数,maximumPoolSize 表示最大线程数,keepAliveTime 表示非核心线程空闲存活时间,TimeUnit 是时间单位,workQueue 是任务等待队列,ThreadFactory 用于创建线程,RejectedExecutionHandler 是任务达到最大容量后的拒绝策略。线程池通过这些参数控制线程创建、任务排队和资源释放。

21. redis为什么这么快?

Redis 快的主要原因:基于内存存储 + 单线程事件模型 + 高效数据结构 + IO多路复用。

Redis 快主要有几个原因:第一,Redis 基于内存存储,避免了磁盘 IO;第二,Redis 使用高效的数据结构,比如 Hash、跳表等;第三,Redis 使用 IO 多路复用,一个线程可以处理大量客户端连接;第四,Redis 的核心命令执行采用单线程模型,避免了线程切换和锁竞争;第五,Redis 操作简单,数据结构针对高性能场景进行了优化。

22. 说一下redis的常用数据类型及使用场景

Redis 提供不同数据结构,是为了适配不同业务场景。

Redis 常用数据类型包括 String、Hash、List、Set、ZSet。String 常用于缓存和计数器,Hash 适合存储对象,List 可以实现消息队列,Set 用于去重和集合运算,ZSet 常用于排行榜。实际项目会根据数据特点选择不同的数据结构。

23. 什么是aop?说一下实现aop的步骤?有哪些通知?项目中哪里用到了aop?

AOP 是把一些与业务无关但很多地方都需要的功能(例如日志、权限、事务)抽取出来,在不修改业务代码的情况下统一增强业务方法。

AOP 是 Spring 提供的面向切面编程思想,用于将日志、权限、事务等公共功能从业务代码中抽离,通过动态代理方式在运行期间对目标方法进行增强。实现 AOP 主要步骤是引入 spring-boot-starter-aop 依赖,创建切面类使用 @Aspect 和 @Component 注解,定义切入点 @Pointcut,然后通过 @Before、@After、@Around 等通知实现增强逻辑。项目中常用于接口日志记录、权限校验、接口耗时统计以及事务控制,其中 Spring 的 @Transactional 底层也是通过 AOP 实现。

24. Spring中的Bean是线程安全的吗?

Spring Bean 默认不是线程安全的,是否线程安全取决于 Bean 的作用域和 Bean 内部是否有共享状态。

Spring Bean 默认是单例的,但是单例 Bean 不代表线程安全。线程安全主要取决于 Bean 是否存在共享状态。如果 Bean 是无状态的,例如 Service 中只处理方法参数,一般是线程安全的;如果 Bean 中定义了成员变量并被多个线程修改,就可能出现线程安全问题。实际开发中通常通过设计无状态 Bean、使用线程安全集合、锁机制或者 ThreadLocal 来保证线程安全。

25. Springboot自动配置原理?

Spring Boot 自动配置就是根据项目中引入的依赖和配置文件,自动判断需要哪些 Bean,并自动创建和配置这些 Bean,减少手动配置。

Spring Boot 自动配置是通过 @EnableAutoConfiguration 实现的。项目启动时,Spring Boot 会加载 META-INF 中定义的自动配置类,然后根据条件注解(例如 @ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty)判断当前环境是否满足条件,如果满足就自动向 Spring 容器中注册对应的 Bean。这样开发者只需要引入对应 starter 依赖和简单配置,就可以使用相关功能。

26. 说下linux常见的命令有哪些?

Linux 常用命令主要包括文件操作、进程管理、网络排查和服务部署相关命令。比如文件操作使用 ls、cd、mkdir、cp、mv、rm;查看日志使用 cat、tail -f、grep;进程管理使用 ps、top、kill;网络排查使用 ping、netstat、curl;磁盘和资源查看使用 df、du、free;部署 Spring Boot 服务时常用 java -jar、nohup、systemctl 等命令。

相关推荐
matlabgoodboy2 小时前
计算机毕设代做|Java Python Matlab APP 全套开发设计
java·python·课程设计
程序员雷欧3 小时前
环形缓冲区深度解析:从基础原理到Disruptor源码的全面剖析
java
xiaoqiMikko3 小时前
Dependabot 面板全绿,不代表你的 Tomcat 没洞
java·spring boot
前端开发张小七3 小时前
Java 学习笔记 · 第三课:多线程与并发编程(线程、同步、死锁、Lock、乐观锁与悲观锁)
java·后端·程序员
花生了什么事o4 小时前
JVM 垃圾回收:对象如何被判定和回收
java·jvm
evans在进步4 小时前
HashMap 为什么线程不安全?ConcurrentHashMap 如何解决?
java·spring boot·spring
我命由我123454 小时前
匈牙利命名法
java·服务器·后端·学习·java-ee·kotlin·学习方法
闲猫4 小时前
LangChain / Integrations / Integrations by component / Tool
java·数据库·langchain
小田的博客4 小时前
SAP MM 供应商银行主数据更新报错!message R1228!
android·java·服务器
范什么特西5 小时前
知识总结03
java