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

Java十道高频面试题(一)

Java基础与集合

1. HashMap的底层数据结构是什么?(JDK 1.7 vs 1.8)

考察点:数据结构演进、哈希冲突解决、扩容死循环问题。

参考答案

HashMap在JDK 1.7和1.8中有着本质的区别,主要体现在底层结构和扩容机制上:

  1. 底层数据结构

    • JDK 1.7:采用数组 + 链表。当发生哈希冲突时,使用链表存储,且采用头插法插入新节点。
    • JDK 1.8:采用数组 + 链表 + 红黑树
      • 优化:当链表长度大于8且数组长度大于64时,链表会转换为红黑树。
      • 目的:将查询时间复杂度从 O(n)O(n) 降低到 O(log⁡n)O(logn) ,解决了哈希冲突严重时查询效率低的问题。
      • 插入方式:改为尾插法,保持了元素的顺序。
  2. 扩容机制(核心区别)

    • JDK 1.7(头插法导致的死循环):在多线程环境下扩容时,由于头插法会反转链表顺序,可能导致链表形成环形结构(死循环),导致CPU占用率100%。
    • JDK 1.8(尾插法解决死循环):扩容时保持链表顺序,虽然HashMap在1.8中依然是线程不安全的(存在数据覆盖问题),但彻底解决了死循环的问题。
    • 扩容机制:默认初始容量为16,负载因子为0.75。当元素个数超过容量 * 负载因子时,触发扩容,容量变为原来的2倍,并进行重新哈希(Rehash)。
  3. 哈希计算

    • JDK 1.8:优化了哈希值的计算方式,减少了哈希碰撞的概率,且在扩容时不需要重新计算hash值,而是通过高位运算判断元素位置,效率更高。
2. ConcurrentHashMap如何保证线程安全?(JDK 1.7 vs 1.8)

考察点:锁粒度进化、分段锁 vs CAS+Synchronized。

参考答案

ConcurrentHashMap(CHM)在JDK 1.7和1.8中采用了完全不同的并发控制策略,核心在于锁粒度的不断细化:

  1. JDK 1.7:分段锁(Segment Lock)

    • 结构:采用Segment数组 + HashEntry数组。Segment继承自ReentrantLock,相当于一个小的HashMap。
    • 原理:将数据分成一段一段存储,给每一段数据配一把锁(默认16个Segment)。
    • 并发度:默认支持16个线程同时并发写(取决于Segment数量)。
    • 缺点:锁粒度较粗(锁住整个Segment),且Segment数量初始化后不可变,内存开销较大。
  2. JDK 1.8:CAS + synchronized(细粒度锁)

    • 结构:抛弃了Segment,结构与HashMap 1.8一致,即Node数组 + 链表 + 红黑树
    • 原理
      • 空桶插入:使用CAS(Compare-And-Swap)操作尝试无锁插入,性能极高。
      • 冲突插入:当发生哈希冲突时,使用synchronized锁住当前桶(Bucket)的头节点
    • 并发度:理论上取决于数组长度(默认16,动态扩容),只要哈希不冲突,不同线程可以操作不同的桶,互不干扰。
    • 优势:锁粒度从“段”细化到了“节点/桶”,并发性能大幅提升。同时,读操作(get)完全无锁,依靠volatile保证可见性。
3. 为什么重写equals()必须重写hashCode()?

考察点:Object类规范、哈希集合原理。

参考答案
这是为了保证对象在哈希集合(如HashMap、HashSet)中的正确性。

  • 规范:Java规定,如果两个对象通过equals()比较返回true,那么它们的hashCode()必须相同。
  • 后果:如果只重写equals而不重写hashCode,两个逻辑上相等的对象可能会计算出不同的哈希值。在存入HashMap时,它们会被放入不同的桶中,导致无法正确获取或去重,违背了集合的设计原则。

并发编程

4. 线程池的核心参数有哪些?工作流程是怎样的?

考察点:ThreadPoolExecutor、生产环境配置。

参考答案
核心参数有7个,最关键的5个是:

  1. corePoolSize:核心线程数(常驻线程)。
  2. maximumPoolSize:最大线程数。
  3. workQueue:任务阻塞队列。
  4. keepAliveTime:非核心线程的空闲存活时间。
  5. RejectedExecutionHandler:拒绝策略。

工作流程
当提交一个新任务时:

  1. 如果当前线程数 <corePoolSize,创建新核心线程执行。
  2. 如果核心线程已满,任务加入workQueue
  3. 如果队列也满了,且线程数 <maximumPoolSize,创建非核心线程执行。
  4. 如果队列满了且线程数已达最大值,执行RejectedExecutionHandler(默认AbortPolicy抛异常)。
5. synchronized和ReentrantLock的区别?

考察点:锁的实现、功能特性。

参考答案

  • 实现层面synchronized是JVM层面的关键字(内置锁),自动加锁释放;ReentrantLock是JDK API层面的类(java.util.concurrent.locks),需要手动lock()unlock()
  • 功能特性
    • synchronized:操作简单,JDK 1.6后进行了大量优化(偏向锁、轻量级锁),不可中断,非公平锁。
    • ReentrantLock:功能更强大,支持可中断尝试获取锁tryLock)、公平锁以及多条件变量(Condition)。
  • 选择:代码简洁性优先选synchronized,需要高级功能(如公平锁、中断)选ReentrantLock
6. ThreadLocal的底层原理及内存泄漏问题?

考察点:线程隔离、弱引用。

参考答案

  • 原理:每个Thread内部维护了一个ThreadLocalMapThreadLocal作为Key(弱引用),存储的数据作为Value(强引用)。获取数据时,从当前线程的Map中通过ThreadLocal实例取出Value。
  • 内存泄漏
    • 原因ThreadLocalMap中的Key是弱引用,容易被GC回收;但Value是强引用。如果线程复用(如在线程池中),且没有手动移除数据,Key被回收后,Value将无法访问也无法回收,导致内存泄漏。
    • 解决:使用完ThreadLocal后,务必调用remove()方法清理数据。

JVM与Java新特性

7. JDK 21的虚拟线程(Virtual Threads)是什么?

考察点:2026年面试热点、高并发新方案。

参考答案
虚拟线程是JDK 21引入的重磅特性(Project Loom),是一种轻量级线程

  • 核心:它是用户态线程,由JVM调度,而不是直接映射到操作系统内核线程(OS Thread)。
  • 优势:创建成本极低(内存占用极小),可以轻松创建百万级并发线程。它解决了传统线程“一请求一线程”模型在高并发IO场景下的资源瓶颈。
  • 应用:彻底取代了WebFlux等响应式编程的复杂写法,可以用同步代码写出异步的高性能服务。
8. JVM的垃圾回收算法有哪些?G1收集器的特点?

考察点:内存管理、调优基础。

参考答案

  • 常见算法:标记-清除(碎片化)、复制算法(新生代常用)、标记-整理(老年代常用)。
  • G1收集器
    • 特点:面向服务端,将堆内存划分为多个独立的Region。
    • 优势:可预测的停顿时间模型。它能根据用户设定的停顿时间目标,动态调整回收的Region数量。
    • 适用:适合大内存(6GB+)、多核CPU且对停顿时间有要求的场景。

Spring框架

9. Spring Boot的自动配置原理是什么?

考察点:框架源码、约定优于配置。

参考答案
核心在于@EnableAutoConfiguration注解。

  1. 加载:通过@Import导入AutoConfigurationImportSelector
  2. 读取:扫描classpath下的META-INF/spring.factories文件(或新版META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports)。
  3. 筛选:读取所有候选配置类,并利用@Conditional系列注解(如@ConditionalOnClass@ConditionalOnMissingBean)进行按需加载。
  4. 生效:只有当类路径下存在特定类(如RedisTemplate)且容器中不存在相关Bean时,自动配置才会生效。
10. Spring事务失效的常见场景有哪些?

考察点:AOP代理机制、实战避坑。

参考答案

  • 方法非public:Spring事务只支持public方法。
  • 自调用:同一个类中,非事务方法调用事务方法(this.method()),绕过了代理对象,导致事务失效。
  • 异常被捕获:在方法内部try-catch了异常,没有抛出,事务管理器无法感知异常,从而无法回滚。
  • 数据库引擎:数据库表引擎不支持事务(如MySQL的MyISAM)。
  • 异常类型不匹配:默认只回滚RuntimeExceptionError,如果抛出Checked Exception(如IOException)且未配置rollbackFor,事务不会回滚。
    这10道题覆盖了Java后端开发最核心的知识体系,建议你结合自己的项目经验进行记忆。
http://www.jsqmd.com/news/803587/

相关文章:

  • AI推广的核心原理是什么?
  • 2026年安阳直流电弧炉与工业固废处理设备深度横评指南|优能德电气 18537242761 - 企业名录优选推荐
  • 从零实现分布式存储系统(第二阶段):网络层 + NameNode + DataNode + 容错机制
  • 2026雅思线上小班选课攻略:避开坑班,选择高提分小班课程 - 品牌2025
  • 从触摸事件到RunLoop:一次点击背后,iOS系统到底为你做了哪些事?
  • 别再盲信SOTA!DeepSeek HumanEval原始日志曝光:37次超时、22个未覆盖corner case,附可复用的稳定性加固补丁
  • 模拟真人手写软件,支持随机调节
  • 从无人机飞控到机械臂:四元数如何解决万向锁这个‘老大难’问题?
  • FAA Part 107商业无人机法规深度解析:从合规操作到进阶应用
  • 硬件安全验证:Assertain框架与LLM生成断言实践
  • Robodyssey机器人教育:从STEM理念到项目实践,点燃孩子科技兴趣
  • 苏锡常制造企业短视频抖音号视频号优化运营推广公司实力排行盘点 - 速递信息
  • 2026宁波婚纱摄影排名|品牌硬实力多维对比 - charlieruizvin
  • 【数据科学】【会计学】第八篇 预算制定领域
  • 2026锁扣管桩服务商推荐:围堰支护/基坑支护哪家好选型指南 - 速递信息
  • 告别枯燥语法!深度拆解 easy-vibe:2026 年初学者迈入“Vibe Coding”的第一课
  • 专业级Windows系统依赖修复:3步彻底解决Visual C++运行库问题
  • AI Agent开源情报工具箱:Bash脚本自动化OSINT侦察实践
  • 告别格式烦恼:北航毕业论文LaTeX模板的5步终极指南
  • 量子计算威胁下的密码安全:从后量子密码到密码敏捷性实战解析
  • 清末阜阳武将程文炳的家国判断
  • 考研复试被问懵?别怕!这份高数核心概念速查手册(含泰勒展开、傅里叶变换)帮你稳住
  • pg_rman部署和使用实例
  • Taotoken 官方价折扣与活动价助力个人开发者降低创新门槛
  • GetQzonehistory:3步搞定QQ空间历史说说备份的终极Python工具
  • IFN-α Receptor Recognition Peptide 1 (IRRP1)
  • 上饶装修公司靠谱性判定:从资质到落地的技术维度解析 - 奔跑123
  • 别再折腾CUDA了!用Anaconda Navigator一键搞定DeepLabCut-GPU版(附清华/阿里镜像配置)
  • 在团队协作中通过Taotoken实现API调用权限与审计管理
  • VQA实战笔记:从数据加载到特征工程的关键代码解析