版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java难点高频面试题及详细答案(实战向)一、Java基础核心难点1、==和equals的核心区别?重写equals为什么必须重写hashCode?详细答案:1)核心区别==是运算符,对于基本数据类型,比较的是数值本身;对于引用类型,比较的是对象的内存地址。equals是Object类的方法,原生默认实现和==一致,也是比较对象地址。大部分业务类(String、Integer)会重写该方法,重写后比较的是对象的内容属性值。2)重写equals必须重写hashCode的原因Java哈希集合(HashMap、HashSet)的存储规则是:先判断hashCode是否一致,再判断equals是否相等。如果只重写equals不重写hashCode,会出现内容相等的两个对象,hashCode值不同的情况。此时哈希集合会判定为两个不同对象,导致去重失效、取值失败,违反Java哈希规范。核心原则:相等的对象必须hashCode相等,hashCode相等的对象不一定相等。2、String、StringBuilder、StringBuffer的区别?为什么String不可变?详细答案:1)三者核心区别String:字符串常量,底层是被final修饰的char数组(JDK9后为byte数组),不可变;线程安全;频繁拼接字符串会产生大量中间垃圾对象,效率极低。StringBuilder:可变字符串,线程不安全,无锁,拼接效率高,日常开发单线程场景首选。StringBuffer:可变字符串,线程安全,所有方法加了synchronized锁,多线程并发操作字符串时使用,效率低于StringBuilder。2)String不可变的原因底层存储字符的数组被private+final修饰,且没有提供任何修改数组内容的公开方法。每次对String进行拼接、截取、替换操作,都会生成一个全新的字符串对象,原对象不会被修改。不可变的优势:保证字符串常量池复用、线程绝对安全、作为HashMap键值不会出现哈希值变动问题。3、final、finally、finalize的区别?final修饰变量的细节详细答案:1)三者完全无关,作用不同final:修饰符,用于限制权限。修饰类则类不可被继承;修饰方法则方法不可重写;修饰变量则变量不可被二次赋值。finally:异常处理关键字,搭配try-catch使用,代码无论正常执行还是抛出异常,最终都会执行(除JVM退出等极端情况),常用于释放资源。finalize:Object类的废弃方法,JDK9废弃。是垃圾回收前触发的回调方法,本意是资源收尾,但执行时机不确定、无法保证调用,业务中绝对不用。2)final变量细节基本类型final变量:数值一旦赋值,永久不可修改。引用类型final变量:引用地址不可修改,但对象内部的属性可以修改。比如final修饰List,不能重新赋值新List,但可以add、remove元素。二、JVM核心难点(面试高频)1、JVM内存区域划分?堆和栈的核心区别详细答案:JVM运行时数据区分为5个核心区域:1)程序计数器:线程私有,记录当前线程执行的字节码行号,是唯一没有内存溢出的区域。2)虚拟机栈(栈内存):线程私有,存储局部变量、方法栈帧、操作数栈。方法调用和结束对应栈帧入栈出栈,栈内存空间小、速度快。3)本地方法栈:线程私有,为native本地方法服务。4)堆内存:线程共享,JVM最大内存区域,所有对象实例、数组都在堆中分配,是垃圾回收的核心区域。5)方法区:线程共享,存储类信息、常量、静态变量、即时编译代码。JDK8后元空间取代永久代,元空间使用本地内存,不受JVM堆内存限制。堆栈核心区别:栈内存随线程生命周期,自动释放;堆内存随JVM运行,需GC回收;栈存局部变量,堆存对象实例。2、GC垃圾回收机制?CMS和G1的优缺点及适用场景详细答案:1)GC核心逻辑:只回收堆内存中无引用的无效对象,核心是标记、清除、复制、整理四种算法。年轻代多用复制算法,老年代多用标记清除、标记整理算法。2)CMS收集器(老年代并行收集器)优点:并发收集、低停顿,垃圾回收时大部分阶段和用户线程并行执行,适合对响应速度要求高的应用。缺点:产生内存碎片、无法处理浮动垃圾、CPU资源占用高,大内存场景效率差。3)G1收集器(分区收集器)优点:将堆内存划分为多个大小相等的分区,可精准控制停顿时间,兼顾吞吐量和低延迟,自动整理内存碎片,适合大堆内存(4G以上)应用。缺点:小内存场景下,吞吐量不如CMS,算法复杂度高。实际开发:小内存、追求高吞吐量用CMS;大内存、追求低停顿用G1,JDK9+默认G1。3、内存溢出和内存泄漏的区别?常见场景及解决办法详细答案:1)内存泄漏:程序中无用对象持续被引用,GC无法回收,内存占用越来越高,是过程问题。常见场景:静态集合持有对象、未关闭流/连接、线程池线程常驻、内部类持有外部类引用。2)内存溢出:JVM没有足够内存分配新对象,程序直接报错OOM,是结果问题。内存泄漏长期积累最终会导致内存溢出。常见解决方式:排查内存泄漏代码、调整JVM参数(增大堆内存)、优化对象创建逻辑、及时释放资源。三、Java并发编程难点1、synchronized和Lock的核心区别?底层原理差异详细答案:1)底层原理不同synchronized:JVM层面的内置锁,基于对象头的MarkWord实现,隐式加锁解锁,底层经历偏向锁、轻量级锁、重量级锁升级过程。Lock(ReentrantLock):API层面的锁,基于AQS队列同步器实现,显式调用lock()加锁、unlock()解锁。2)核心功能差异synchronized:不可中断、不支持超时、非公平锁、只能单一条件等待。ReentrantLock:可中断、支持超时锁、可公平/非公平切换、支持多条件队列、可重复锁。3)使用场景:简单同步场景用synchronized(代码简洁、JVM优化高效);复杂并发控制(超时、可中断、多条件)用ReentrantLock。2、volatile关键字的作用?不能保证原子性的原因详细答案:1)volatile两大核心作用:保证可见性、禁止指令重排,不保证原子性。可见性:一个线程修改volatile变量,其他线程立即感知最新值,避免变量缓存到工作内存。指令重排:禁止编译器和CPU对volatile变量的读写操作进行指令重排序,解决单例模式DCL的空指针问题。2)不保证原子性的原因原子性是指操作不可拆分,而volatile只能保证单次读写可见。常见的i++操作是读取、自增、写入三步操作,volatile只能保证读取和写入可见,无法保证三步操作整体不被线程打断,多线程下会出现数据覆盖。解决方案:搭配synchronized、ReentrantLock或Atomic原子类使用。3、线程池核心参数?为什么不推荐使用Executors创建线程池?详细答案:1)线程池7大核心参数核心线程数、最大线程数、空闲超时时间、时间单位、任务队列、线程工厂、拒绝策略。执行流程:任务提交后,优先创建核心线程执行;核心线程满则进入队列;队列满则创建非核心线程;达到最大线程数则触发拒绝策略。2)禁止使用Executors的原因(阿里规范)newFixedThreadPool/newSingleThreadExecutor:使用无界队列,任务堆积过多会导致OOM内存溢出。newCachedThreadPool:最大线程数无上限,高并发下会创建大量线程,导致CPU爆满、线程溢出。正确做法:手动创建ThreadPoolExecutor,自定义参数和有界队列,指定拒绝策略。四、集合框架难点1、HashMap底层原理?JDK7和JDK8的核心区别详细答案:HashMap底层是数组+链表+红黑树(JDK8),基于哈希表实现,用于存储键值对,允许null键null值,线程不安全。1)JDK7底层:数组+单向链表,无红黑树,哈希冲突过多时链表无限拉长,查询效率极低。2)JDK8核心优化新增红黑树:链表长度大于8、数组容量大于64时,链表转为红黑树,查询时间复杂度从O(n)优化为O(logn)。优化哈希扰动算法:减少哈希冲突概率。扩容优化:JDK7头插法,并发易出现环形链表死循环;JDK8尾插法,保留原有顺序,规避死循环问题。3)核心参数:默认容量16,负载因子0.75,扩容阈值=容量*负载因子。2、HashMap线程不安全的具体表现?如何解决?详细答案:1)线程不安全场景JDK7:并发扩容时,头插法会导致链表环形引用,触发死循环,CPU飙升。JDK8:虽解决了环形链表问题,但并发put操作会出现数据覆盖、数据丢失,多线程put相同位置数据会互相覆盖。2)解决方案方式一:使用ConcurrentHashMap(高并发首选),分段锁+CAS+synchronized,并发效率高。方式二:使用HashTable,全表锁,并发效率极低,基本废弃。方式三:Collections.synchronizedMap包装,效率一般。3、ConcurrentHashMap底层原理(JDK8)详细答案:JDK8ConcurrentHashMap底层为数组+链表+红黑树,摒弃JDK7分段锁,采用CAS+synchronized实现并发安全。核心逻辑:1)空数组位置插入数据,使用CAS无锁操作,性能极高。2)数组已有数据,对链表/红黑树的头节点加synchronized锁,只锁定当前哈希桶,不影响其他桶操作,并发粒度极小。3)扩容采用多线程协助扩容机制,提升扩容效率。4)不允许null键null值,避免并发场景下的歧义问题。五、Spring核心难点1、SpringIoC容器原理?Bean的生命周期详细答案:1)IoC核心思想:控制反转,将对象的创建、初始化、依赖管理交给Spring容器,告别手动new对象,实现解耦。依赖注入是IoC的具体实现方式。2)Bean完整生命周期加载配置文件->扫描Bean->实例化对象(无参构造)->填充属性(依赖注入)->初始化前置处理(Bean后置处理器)->初始化方法(init-method)->初始化后置处理->Bean就绪可用->容器关闭执行销毁方法。2、SpringAOP原理?动态代理JDK和CGLIB区别详细答案:1)AOP核心:面向切面编程,基于动态代理实现,在不修改原有代码的前提下,对方法进行增强,常用于日志、事务、权限校验。2)两种动态代理区别JDK动态代理:基于接口实现,只能代理实现接口的类,速度快,无需引入额外依赖。CGLIB动态代理:基于子类继承实现,可以代理无接口的普通类,通过字节码增强实现,Spring默认优先使用JDK代理,无接口则使用CGLIB。3、Spring事务失效的常见场景详细答案:Spring事务基于AOP动态代理,所有破坏代理调用的场景都会导致事务失效,常见8种场景:1)方法权限为非public,代理无法拦截。2)同类中方法内部调用(this调用),绕过代理对象。3)事务传播机制配置错误(如REQUIRES_NEW使用不当)。4)异常类型不匹配(默认只回滚RuntimeException,捕获Exception不回滚)。5)手动捕获异常未抛出,AOP无法感知异常。6)数据库引擎不支持事务(MyISAM)。7)多线程场景下,事务无法跨线程传递。8)事务嵌套导致回滚失效。六、数据库&Redis难点1、MySQL索引失效场景?最左前缀原则详细答案:1)最左前缀原则:联合索引遵循从左到右匹配,查询条件必须匹配最左前列,否则索引失效。比如索引(a,b,c),查询b=?、c=?会失效,查询a=?、a,b=?生效。2)常见索引失效场景like%xxx左模糊查询
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年复工复产安全培训试题附答案
- 2026年电子商务概论程絮森王刊良课后习题附答案解析
- 2026年人工智能随堂测试题及答案
- 儿科常用护理技术
- 药物研发中的药效学评价模型
- 人工智能在外语教学中的创新应用
- 腹腔镜微创嵌顿疝手术对婴幼儿呼吸
- 疑难病例讨论制度深度解析
- 综合岗2026事业编面试自测卷习题汇编
- 护理学科发展历程与启示
- 北师大版数学五年级上册第四单元 用字母表示(一) 基础测试卷
- 2026-2027学年七年级语文上册第一次月考试卷部编版含答案
- 会计核算差错更正管理办法
- 社会工作者考试题库(1000题·含答案与解析)
- 设备日常点检维护管理规范
- 儿童急性呼吸道感染诊疗共识2026
- 电商客服分包合同模板
- 2026山东东诚投资发展有限公司招聘总经理助理5人备考题库及参考答案详解一套
- 高中生物全部知识点系统总结
- 中国华氏巨球蛋白血症诊疗指南(2025版)
- 中国脓毒症诊疗指南2025版
评论
0/150
提交评论