Java高频面试题(含详细实战答案)_第1页
Java高频面试题(含详细实战答案)_第2页
Java高频面试题(含详细实战答案)_第3页
Java高频面试题(含详细实战答案)_第4页
Java高频面试题(含详细实战答案)_第5页
已阅读5页,还剩2页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java高频面试题(含详细实战答案)一、Java基础面试题1、JDK、JRE、JVM的区别是什么?详细答案:三者是层层包含的关系,范围从大到小依次是JDK>JRE>JVM。JVM是Java虚拟机,是Java程序运行的核心环境,只负责解析、执行字节码文件,是跨平台的核心,本身不包含任何开发工具。JRE是Java运行环境,包含了JVM和Java运行所需的核心类库,比如常用的String、集合、IO相关类。只安装JRE的电脑可以运行Java程序,但不能开发Java项目。JDK是Java开发工具包,包含了JRE,同时额外提供了编译、调试、打包等开发工具,比如javac编译器、java运行命令、jar打包工具等。做Java开发必须安装JDK。2、==和equals()的区别?详细答案:==是运算符,equals是Object类的方法,二者比对逻辑完全不同。基本数据类型使用==,比较的是变量的实际数值;引用数据类型使用==,比较的是对象的内存地址,也就是判断两个变量是不是指向同一个对象。equals方法默认情况下和==效果一致,也是比较对象内存地址。但像String、Integer、自定义实体类都会重写equals方法,重写后不再比较地址,而是比较对象的内容、属性值是否相等。日常开发中,比较字符串、对象内容是否一致,必须用equals;判断是否是同一个对象,用==。同时使用equals时建议常量在前,避免空指针异常。3、String、StringBuilder、StringBuffer的区别?详细答案:1、可变性:String是不可变字符串,底层是被final修饰的字符数组,每次字符串拼接、修改都会生成新的字符串对象,频繁操作会产生大量无用垃圾。StringBuilder和StringBuffer是可变字符串,修改内容不会创建新对象。2、线程安全:StringBuffer所有方法都加了synchronized锁,线程安全,适合多线程环境;StringBuilder没有加锁,线程不安全,性能更高,是单线程字符串拼接首选。3、性能:单线程下性能排序:StringBuilder>StringBuffer>String。实际开发场景:少量字符串拼接直接用String;大量循环拼接、单线程场景用StringBuilder;多线程共享字符串操作场景用StringBuffer。4、final、finally、finalize的区别?详细答案:三者只是名字相似,功能完全无关。final是修饰符,可以修饰类、方法、变量。final修饰的类不能被继承;修饰的方法不能被重写;修饰的变量是常量,只能赋值一次,引用类型变量地址不可变,但对象内容可以改。finally是异常处理代码块,和try、catch配合使用,无论代码是否抛出异常、是否return,finally中的代码一定会执行(除了手动退出程序、断电等极端情况),主要用于关闭流、释放资源。finalize是Object类的废弃方法,JDK9之后已废弃。原本作用是垃圾回收器回收对象前,触发该方法执行收尾清理工作,但执行时机不确定、无法保证调用,开发中完全不使用。二、面向对象面试题1、面向对象的四大特性?分别怎么理解?详细答案:Java面向对象四大核心特性:封装、继承、多态、抽象。1、封装:将类的属性私有化,通过public的get、set方法对外提供访问入口。核心目的是隐藏内部实现细节,保护数据安全,统一访问规则,降低代码耦合度。2、继承:子类继承父类的属性和方法,实现代码复用。子类可以在父类基础上扩展新功能,不用重复编写通用代码。Java是单继承,一个子类只能有一个直接父类,避免多继承的逻辑冲突。3、多态:同一个行为,不同子类有不同的实现方式。核心实现是父类引用指向子类对象,重写父类方法。多态可以让代码扩展性更强,新增子类无需修改原有代码。4、抽象:抽取事物的共性特征和行为,忽略细节。通过抽象类和接口实现,抽象类有构造方法、可以有普通方法和抽象方法;接口全部是抽象规范(JDK8后支持默认方法、静态方法),用于定义行为标准。2、接口和抽象类的区别?详细答案:1、继承规则:抽象类只能单继承;接口可以多实现,一个类可以实现多个接口,解决单继承的局限性。2、成员修饰符:抽象类的成员变量可以是任意修饰符;接口的常量默认是publicstaticfinal,方法默认是publicabstract。3、构造方法:抽象类有构造方法,用于子类初始化父类成员;接口没有构造方法,不能实例化。4、使用场景:抽象类用于抽取共性模板,包含通用属性和通用方法;接口用于定义行为规范,只定义要做什么,不限制怎么做。3、重写和重载的区别?详细答案:1、重载:发生在同一个类中,方法名相同,参数列表(个数、类型、顺序)不同,和返回值、访问修饰符无关。属于编译期静态绑定,是类中方法的多态。2、重写:发生在父子类之间,方法名、参数列表、返回值必须完全一致,访问权限子类必须大于等于父类,抛出异常范围必须小于等于父类。属于运行期动态绑定,是面向对象核心多态的体现。简单总结:重载是“同一个类,同名不同参”,重写是“子类改父类,一模一样重新实现”。三、集合框架面试题1、ArrayList和LinkedList的区别?详细答案:1、底层结构:ArrayList底层是动态数组;LinkedList底层是双向链表。2、查询效率:ArrayList支持随机访问,通过下标直接定位元素,查询速度极快;LinkedList没有下标,查询需要从头遍历,速度慢。3、增删效率:ArrayList增删元素时,需要移动数组元素、扩容缩容,效率低;LinkedList只需要修改节点指针,无需移动元素,首尾增删效率高。4、内存占用:ArrayList会预留冗余容量,存在内存浪费;LinkedList每个节点都要存储前后节点指针,单个元素内存占用更高。实际开发:查询多、增删少用ArrayList;频繁首尾增删、极少查询用LinkedList。2、HashMap的底层原理?JDK1.8做了哪些优化?详细答案:HashMap底层核心是数组+链表+红黑树,基于哈希表实现,用于存储键值对数据,key唯一可null,value可null。存储流程:通过key的hash值计算数组下标,下标位置无元素则直接存入;有元素则发生哈希冲突,采用链表法解决;链表长度超过8且数组容量大于等于64时,链表转为红黑树,提升查询效率。JDK1.8优化点:1、底层由纯数组+链表,升级为数组+链表+红黑树,解决哈希冲突严重时链表过长、查询效率极低的问题;2、优化hash算法,减少哈希碰撞概率;3、扩容机制优化,新增高低位拆分,无需重新计算hash值;4、链表长度阈值优化,长度大于8转红黑树,小于6退化为链表。3、HashMap和Hashtable的区别?详细答案:1、线程安全:HashMap线程不安全;Hashtable所有方法加锁,线程安全,但并发性能极差。2、null值支持:HashMap允许key和value为null;Hashtable不允许键值为null,会直接空指针报错。3、效率:HashMap无锁,读写效率高;Hashtable全局锁,并发场景下所有线程阻塞,性能极低。4、继承结构:HashMap继承AbstractMap;Hashtable继承Dictionary,是老旧废弃集合。实际开发:单线程用HashMap;多线程不用Hashtable,优先用ConcurrentHashMap。四、多线程面试题1、线程和进程的区别?详细答案:进程是操作系统资源分配的最小单位,线程是CPU调度的最小单位。一个进程包含多个线程,同一个进程内的线程共享堆内存、方法区资源,相互通信方便;进程之间资源完全独立,互不干扰,通信成本极高。进程开销大、稳定性高,一个进程崩溃不影响其他进程;线程开销小、效率高,一个线程异常崩溃,会导致整个进程终止。2、synchronized和Lock的区别?详细答案:1、锁类型:synchronized是JVM底层内置锁,自动加锁释放锁;Lock是Java代码层面的显式锁,需要手动lock()加锁、unlock()释放锁。2、灵活性:Lock功能更强,支持可中断锁、超时锁、公平锁、读写锁;synchronized只能是非公平锁,无法中断、无法设置超时。3、性能:JDK1.6之后synchronized做了偏向锁、轻量级锁、重量级锁优化,性能大幅提升,和Lock差距很小;高并发竞争激烈场景下,Lock性能更优。4、使用场景:简单同步场景优先用synchronized,代码简洁不易出错;复杂并发控制、需要公平锁、读写分离锁场景用Lock。3、volatile关键字的作用?能保证线程安全吗?详细答案:volatile有两大核心作用:保证可见性、禁止指令重排。可见性:一个线程修改volatile变量,会立即刷新到主内存,其他线程能立刻感知到最新值,解决多线程变量缓存不一致问题。禁止重排:编译器和CPU不会对volatile修饰的变量指令做乱序优化,保证代码执行顺序和编写顺序一致,常用于单例模式防止指令重排导致的空指针问题。volatile不能保证原子性,无法保证线程安全。比如i++操作,是读取、计算、赋值三步操作,volatile只能保证可见性,无法阻止多线程同时操作,会出现数据覆盖问题。需要保证原子性必须用synchronized、Lock或者Atomic原子类。五、JVM面试题1、JVM内存区域划分?详细答案:JVM运行时数据区分为五大区域,其中线程私有区3个、线程共享区2个。线程私有(随线程创建销毁):1、程序计数器:记录当前线程执行的字节码行号,是唯一一个没有内存溢出的区域;2、虚拟机栈:存储局部变量、方法栈帧,方法调用和执行都依赖该区域,栈溢出、栈内存不足报错都出自这里;3、本地方法栈:用于执行native本地方法。线程共享(全局唯一,JVM启动创建):1、堆内存:所有对象、数组的存储区域,是垃圾回收的主要区域,分为新生代、老年代;2、方法区:存储类信息、常量、静态变量、即时编译代码,JDK1.8后替换为元空间,使用本地内存,不再占用堆内存。2、GC垃圾回收机制?哪些对象会被回收?详细答案:GC是JVM自动回收堆内存中无效对象的机制,无需手动释放内存,避免内存泄漏。判定对象可回收的核心算法是可达性分析:以GC根对象为起点遍历,没有被遍历到、没有任何引用指向的对象,就是无效对象,会被GC回收。GC根对象包括:虚拟机栈中引用的对象、静态变量引用对象、常量引用对象、本地方法栈引用对象。垃圾回收分MinorGC(新生代回收,频率高、速度快)、FullGC(整堆回收,包含新生代、老年代,频率低、速度慢,尽量避免频繁触发)。3、常见的OOM内存溢出原因?详细答案:1、堆内存溢出:创建大量对象、集合无限添加元素、静态集合持有对象不释放,导致堆内存占满;2、栈内存溢出:方法递归层数过深、方法嵌套调用过多,栈帧数量超出最大限制;3、元空间溢出:动态生成大量类、反射频繁创建类对象,元空间内存耗尽;4、直接内存溢出:NIO使用ByteBuffer分配大量直接内存,未手动释放。六、Spring核心面试题1、SpringIOC的原理?详细答案:IOC即控制反转,核心是把对象的创建、管理、依赖注入权限交给Spring容器,告别手动new对象。传统开发是开发者主动创建对象、管理依赖;IOC模式下,开发者只需要声明依赖,Spring容器启动时扫描注解/配置,自动创建Bean对象,存入IOC容器,自动完成依赖注入。核心优势:降低代码耦合度,统一管理对象生命周期,方便后续AOP、事务等功能扩展,提升代码可维护性。2、SpringAOP的原理和使用场景?详细答案:AOP即面向切面编程,核心是在不修改原有业务代码的前提下,对方法进行增强,基于动态代理实现。核心原理:通过切点匹配目标方法,在方法执行前后、异常、返回时植入通知逻辑,实现业务代码和通用功能解耦。常用场景:统一日志记录、接口权限校验、方法性能耗时统计、事务控制、

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论