Java、Spring、SpringMVC、SpringBoot和Redis常见面试题

74 阅读11分钟

Java、Spring、SpringMVC、SpringBoot和Redis常见面试题

一、Java基础

1. JDK、JRE和JVM的区别是什么?

答案:

  • JVM (Java Virtual Machine):Java虚拟机,负责将字节码转换为特定平台的机器码并执行。
  • JRE (Java Runtime Environment):Java运行环境,包含JVM和Java核心类库。
  • JDK (Java Development Kit):Java开发工具包,包含JRE和开发工具(编译器、调试器等)。

2. Java的8种基本数据类型有哪些?

答案:

  • 整型:byte(1字节)、short(2字节)、int(4字节)、long(8字节)
  • 浮点型:float(4字节)、double(8字节)
  • 字符型:char(2字节)
  • 布尔型:boolean(1位)

3. String、StringBuffer和StringBuilder的区别?

答案:

  • String:不可变字符串,每次修改都会创建新对象,线程安全。
  • StringBuffer:可变字符串,支持线程安全的修改操作,使用synchronized关键字。
  • StringBuilder:可变字符串,非线程安全,性能优于StringBuffer,适用于单线程环境。

4. 什么是自动装箱和拆箱?

答案:

  • 自动装箱:基本数据类型自动转换为对应的包装类对象。例如:int i = 10; Integer obj = i;
  • 自动拆箱:包装类对象自动转换为对应的基本数据类型。例如:Integer obj = 10; int i = obj;

5. final关键字的作用?

答案:

  • 修饰类:该类不能被继承。
  • 修饰方法:该方法不能被重写。
  • 修饰变量:该变量不能被重新赋值,必须初始化。

二、Java并发编程

6. 什么是线程和进程?它们的区别?

答案:

  • 进程:操作系统资源分配的基本单位,每个进程有独立的内存空间。
  • 线程:CPU调度的基本单位,共享进程的内存空间。
  • 区别:进程间通信复杂,线程间通信简单;进程切换开销大,线程切换开销小;进程拥有独立资源,线程共享进程资源。

7. synchronized和ReentrantLock的区别?

答案:

  • synchronized:Java内置关键字,自动加锁和释放锁,可重入,非公平锁。
  • ReentrantLock:显式的锁对象,需要手动加锁和释放锁,可重入,支持公平锁和非公平锁。
  • 优势:ReentrantLock提供了中断响应、超时获取锁、条件变量等高级功能。

8. 什么是线程池?为什么使用线程池?

答案:

  • 线程池:管理一组工作线程的资源池,避免频繁创建和销毁线程的开销。
  • 优势
    • 降低资源消耗:复用已有线程
    • 提高响应速度:线程已创建,无需等待
    • 提高线程可管理性:统一分配和监控
    • 提供更多功能:定时执行、单线程执行等

9. Java中的线程池有哪些核心参数?

答案:

  • corePoolSize:核心线程数
  • maximumPoolSize:最大线程数
  • keepAliveTime:非核心线程的空闲时间
  • workQueue:工作队列
  • threadFactory:线程工厂
  • handler:拒绝策略

10. 什么是线程安全?如何实现线程安全?

答案:

  • 线程安全:多线程环境下,程序能正确处理共享资源,不出现数据不一致问题。
  • 实现方式
    • 同步代码块/方法(synchronized)
    • 显式锁(ReentrantLock)
    • 原子类(AtomicXXX)
    • 线程安全的集合类(ConcurrentHashMap等)
    • 线程本地存储(ThreadLocal)

三、Spring框架

11. Spring框架的核心特性有哪些?

答案:

  • 控制反转(IoC):将对象的创建和管理权交给Spring容器
  • 依赖注入(DI):通过构造函数、setter方法或字段注入依赖
  • 面向切面编程(AOP):将横切关注点与业务逻辑分离
  • 声明式事务:通过注解或XML配置管理事务
  • 集成测试:提供测试支持

12. Spring中的Bean的生命周期?

答案:

  1. 实例化Bean(调用构造方法)
  2. 设置Bean属性(依赖注入)
  3. 调用BeanNameAware的setBeanName方法
  4. 调用BeanFactoryAware的setBeanFactory方法
  5. 调用ApplicationContextAware的setApplicationContext方法
  6. 调用BeanPostProcessor的postProcessBeforeInitialization方法
  7. 调用InitializingBean的afterPropertiesSet方法
  8. 调用自定义init-method
  9. 调用BeanPostProcessor的postProcessAfterInitialization方法
  10. Bean就绪,可以使用
  11. 容器关闭时,调用DisposableBean的destroy方法
  12. 调用自定义destroy-method

13. Spring中的依赖注入方式有哪些?

答案:

  • 构造函数注入:通过构造方法传递依赖
  • Setter方法注入:通过setter方法设置依赖
  • 字段注入:直接在字段上使用@Autowired注解
  • 接口注入:实现特定接口进行依赖注入(较少使用)

14. Spring中的AOP的作用是什么?主要应用场景?

答案:

  • 作用:将横切关注点(如日志、事务、安全)与业务逻辑分离,提高代码复用性和可维护性。
  • 应用场景
    • 事务管理
    • 日志记录
    • 权限控制
    • 性能监控
    • 异常处理

15. Spring中的事务传播行为有哪些?

答案:

  • REQUIRED:如果当前没有事务,创建新事务;如果已有事务,加入该事务
  • SUPPORTS:如果当前有事务,加入该事务;如果没有事务,以非事务方式执行
  • MANDATORY:必须在事务中执行,否则抛出异常
  • REQUIRES_NEW:创建新事务,挂起当前事务
  • NOT_SUPPORTED:以非事务方式执行,挂起当前事务
  • NEVER:以非事务方式执行,如果当前有事务,抛出异常
  • NESTED:如果当前有事务,创建嵌套事务;如果没有事务,创建新事务

四、SpringMVC

16. SpringMVC的工作流程是什么?

答案:

  1. 用户发送请求到前端控制器DispatcherServlet
  2. DispatcherServlet根据请求URL调用HandlerMapping
  3. HandlerMapping返回Handler执行链
  4. DispatcherServlet调用HandlerAdapter
  5. HandlerAdapter执行Handler并返回ModelAndView
  6. DispatcherServlet将ModelAndView传递给ViewResolver
  7. ViewResolver解析并返回View
  8. DispatcherServlet渲染View并返回响应

17. SpringMVC中的常用注解有哪些?

答案:

  • @Controller:标识控制器类
  • @RestController:@Controller和@ResponseBody的组合
  • @RequestMapping:映射请求URL
  • @RequestParam:获取请求参数
  • @PathVariable:获取URL路径参数
  • @RequestBody:将请求体转换为对象
  • @ResponseBody:将返回值写入响应体
  • @SessionAttributes:将模型属性存储到session中
  • @ModelAttribute:绑定请求参数到模型属性

18. SpringMVC中的拦截器有什么作用?如何实现?

答案:

  • 作用:拦截用户请求,在请求处理前后执行特定操作。
  • 实现方式
    1. 实现HandlerInterceptor接口
    2. 重写preHandle、postHandle、afterCompletion方法
    3. 在Spring配置文件中注册拦截器

19. SpringMVC中的异常处理机制有哪些?

答案:

  • @ExceptionHandler:在Controller中处理异常
  • @ControllerAdvice:全局异常处理
  • SimpleMappingExceptionResolver:XML配置的异常处理器
  • ResponseStatusExceptionResolver:处理带有@ResponseStatus注解的异常

20. SpringMVC如何实现文件上传?

答案:

  1. 添加依赖:commons-fileupload
  2. 配置MultipartResolver
  3. 在Controller中使用@RequestParam("file") MultipartFile file接收文件
  4. 调用transferTo方法保存文件

五、SpringBoot

21. SpringBoot的主要特点是什么?

答案:

  • 自动配置:根据类路径上的依赖自动配置应用
  • 起步依赖:提供一系列starter POM简化依赖管理
  • 嵌入式容器:内置Tomcat、Jetty等容器
  • 无代码生成和XML配置:基于JavaConfig
  • 生产就绪功能:健康检查、指标监控等
  • 简化Maven配置:提供父POM管理版本依赖

22. SpringBoot的自动配置原理是什么?

答案:

  • 基于@EnableAutoConfiguration注解
  • 扫描classpath下的META-INF/spring.factories文件
  • 根据文件中配置的自动配置类进行加载
  • 通过条件注解(@ConditionalOnClass、@ConditionalOnMissingBean等)决定是否应用配置

23. SpringBoot的核心注解有哪些?

答案:

  • @SpringBootApplication:组合了@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan
  • @SpringBootConfiguration:标识配置类
  • @EnableAutoConfiguration:启用自动配置
  • @ComponentScan:扫描组件
  • @ConfigurationProperties:绑定配置属性
  • @EnableCaching:启用缓存
  • @EnableAsync:启用异步方法

24. SpringBoot和传统Spring项目的区别?

答案:

  • 配置简化:减少XML配置,使用JavaConfig和注解
  • 内嵌容器:无需外部容器,直接运行jar包
  • 依赖管理:starter POM简化依赖配置
  • 自动装配:智能配置,减少手动配置
  • 开发体验:热部署、指标监控等功能
  • 打包方式:可以打包为jar或war

25. SpringBoot中的配置文件有哪些格式?它们有什么区别?

答案:

  • application.properties:键值对格式
  • application.yml:YAML格式,层次结构更清晰

区别:

  • YAML格式更易读,支持层次结构
  • properties格式更通用,兼容性更好
  • YAML对缩进敏感,properties不敏感

六、Redis

26. Redis的特点有哪些?

答案:

  • 内存存储:高性能,读写速度快
  • 持久化:支持RDB和AOF持久化
  • 数据类型丰富:String、List、Set、Hash、ZSet等
  • 支持事务:原子性操作
  • 支持发布订阅:消息队列功能
  • 支持Lua脚本:自定义原子操作
  • 主从复制:高可用
  • 哨兵和集群模式:高可用和横向扩展

27. Redis的数据类型有哪些?使用场景?

答案:

  • String:字符串、数字、二进制数据,用于缓存、计数器、分布式锁
  • List:有序列表,用于消息队列、最新消息排行
  • Set:无序集合,用于去重、共同好友
  • Hash:键值对集合,用于存储对象、用户信息
  • ZSet:有序集合,用于排行榜、计分系统
  • Bitmap:位图,用于统计、签到
  • HyperLogLog:基数统计,用于独立访客统计

28. Redis的持久化机制有哪些?区别?

答案:

  • RDB:快照方式,定期将内存数据保存到磁盘
    • 优点:恢复速度快,文件小
    • 缺点:可能丢失数据
  • AOF:日志方式,记录每个写操作
    • 优点:数据安全性高
    • 缺点:文件大,恢复速度慢
  • 混合持久化:Redis 4.0+支持,结合了两者的优点

29. Redis的缓存穿透、缓存击穿、缓存雪崩的区别和解决方案?

答案:

  • 缓存穿透:查询不存在的数据,导致请求直接打到数据库
    • 解决方案:缓存空对象、布隆过滤器
  • 缓存击穿:热点key过期,大量请求同时访问数据库
    • 解决方案:设置永不过期、互斥锁、缓存预热
  • 缓存雪崩:大量key同时过期,请求全部打到数据库
    • 解决方案:设置随机过期时间、分层缓存、热点数据永不过期

30. Redis的分布式锁如何实现?

答案:

-- 获取锁
SET lock_key random_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脚本保证原子性
  • 考虑锁的重入性、可重试性等

31. Redis的主从复制原理是什么?

答案:

  • 全量同步:从服务器连接主服务器,发送SYNC命令,主服务器生成RDB文件并发送给从服务器
  • 增量同步:主服务器将写操作记录到复制缓冲区,同步给从服务器
  • 心跳机制:从服务器定期发送心跳包,主服务器回应

32. Redis的哨兵机制有什么作用?

答案:

  • 监控:监控主从服务器的运行状态
  • 自动故障转移:当主服务器宕机时,自动将从服务器提升为主服务器
  • 通知:当监控的实例出现问题时,发送通知
  • 配置提供:为客户端提供最新的主服务器地址

33. Redis集群的分片机制是什么?

答案:

  • Redis集群采用虚拟槽分区,共16384个槽位
  • 每个节点负责一部分槽位
  • 通过哈希算法计算key属于哪个槽位
  • CRC16(key) % 16384 = slot

34. Redis中的内存淘汰策略有哪些?

答案:

  • noeviction:不淘汰,内存不足时拒绝写操作
  • allkeys-lru:从所有key中删除最近最少使用的key
  • volatile-lru:从设置了过期时间的key中删除最近最少使用的key
  • allkeys-random:从所有key中随机删除
  • volatile-random:从设置了过期时间的key中随机删除
  • volatile-ttl:删除剩余生存时间最短的key
  • volatile-lfu:从设置了过期时间的key中删除最不经常使用的key
  • allkeys-lfu:从所有key中删除最不经常使用的key

35. Redis与Memcached的区别?

答案:

  • 数据类型:Redis支持丰富的数据类型,Memcached只支持String
  • 持久化:Redis支持持久化,Memcached不支持
  • 内存管理:Redis使用自己的内存分配器,Memcached使用slab分配机制
  • 原子操作:Redis支持更多的原子操作
  • 集群:Redis原生支持集群,Memcached需要客户端实现分布式
  • 事务:Redis支持简单事务,Memcached不支持

以上面试题涵盖了Java、Spring、SpringMVC、SpringBoot和Redis的核心知识点,希望对您有所帮助!