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

下载本文档

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

文档简介

Java高频面试题解惑及详细答案(实战接地气版)一、Java基础核心面试题1.JDK、JRE、JVM的区别与联系?标准答案:三者是层层包含的关系,范围从大到小:JDK>JRE>JVM。JVM是Java虚拟机,是Java程序运行的核心载体,只负责解析和执行字节码文件(.class),不包含任何开发工具,是整个Java跨平台的核心,不同系统有对应版本的JVM。JRE是Java运行环境,包含JVM+Java核心运行类库。它只用于运行已经编译好的Java程序,没有代码编译、调试等开发工具,普通用户运行Java程序只需安装JRE。JDK是Java开发工具包,包含JRE+开发工具(javac编译器、java运行命令、jstack、jmap调试工具等),是开发人员编写、编译、调试Java程序必须安装的工具包。面试加分总结:JDK面向开发,JRE面向运行,JVM面向底层执行,Java跨平台的本质是JVM屏蔽了系统底层差异。2.==和equals的区别?标准答案:==是运算符,既可以比较基本数据类型,也可以比较引用数据类型。基本数据类型比较的是实际数值是否相等;引用数据类型比较的是对象的内存地址是否相同,也就是判断是不是同一个对象。equals是Object类的方法,默认只能比较引用类型。原生的equals方法底层就是==,也是比较对象地址。但像String、Integer这类常用类,都重写了equals方法,重写后不再比较地址,而是比较对象的实际内容、数值是否相等。实战场景:日常开发中,字符串、包装类对比内容统一用equals,基本类型对比用==。3.String、StringBuilder、StringBuffer的区别?标准答案:1.可变性:String是不可变字符串,每次拼接、修改都会生成新的字符串对象,效率极低;StringBuilder和StringBuffer是可变字符串,修改操作直接在原对象上执行,不会产生新对象。2.线程安全:StringBuffer所有方法都加了synchronized锁,线程安全,多线程环境下可用;StringBuilder无锁,线程不安全,多线程并发修改会出现数据错乱。3.执行效率:单线程场景下StringBuilder效率最高,StringBuffer次之,String效率最低。开发使用规范:少量字符串拼接用String;单线程大量拼接用StringBuilder;多线程大量拼接用StringBuffer。4.基本数据类型和包装类的区别?标准答案:1.存储方式:基本类型是系统原生数据类型,直接存储数值,占用内存小;包装类是对象类型,封装了基本类型,存储在堆内存,占用内存更大。2.默认值:基本类型有固定默认值,比如int默认0、boolean默认false;包装类默认值是null,可以区分空值和0值,这是开发中最核心的区别。3.泛型支持:泛型不支持基本类型,只能使用包装类,比如List<Integer>不能写List<int>。4.方法支持:包装类提供了大量工具方法,比如类型转换、数值判断,基本类型没有任何方法。避坑点:包装类存在缓存机制,Integer缓存-128~127,这个区间内的对象用==比较为true,超出区间则为false,开发中包装类对比必须用equals。二、面向对象OOP面试题1.面向对象的四大特性?分别怎么理解?标准答案:封装:将类的属性私有化,通过公开的get/set方法访问属性,隐藏对象内部实现细节,统一访问入口,提高代码安全性和可维护性。继承:子类继承父类的属性和方法,实现代码复用,减少重复代码,同时子类可以扩展自己的独有功能,是多态的前提。Java是单继承,一个子类只能有一个直接父类,支持多接口实现。多态:同一个行为,不同子类有不同的实现方式。核心体现是父类引用指向子类对象,方法重写是多态的核心实现,能提高代码扩展性。抽象:抽取事物的核心共性,忽略次要细节,通过抽象类或接口定义规范,只定义方法声明,不实现具体逻辑,强制子类实现规范,统一代码标准。2.重写和重载的区别?标准答案:重载(Overload):发生在同一个类中,方法名必须相同,参数列表(个数、类型、顺序)必须不同,返回值、修饰符可以随意修改。重载是编译期绑定,属于静态多态,和继承无关。重写(Override):发生在父子类之间,方法名、参数列表、返回值必须和父类完全一致;修饰符权限不能比父类严格,不能抛出比父类更大的异常。重写是运行期绑定,属于动态多态。简易记忆:重载是同一个类里方法花式变形,重写是子类改写父类方法。3.接口和抽象类的区别?标准答案:1.继承限制:抽象类只能单继承;接口可以多实现,解决了Java单继承的局限性。2.成员修饰符:抽象类可以有普通成员变量、构造方法、静态方法、普通方法、抽象方法;接口默认变量是publicstaticfinal(常量),JDK8前只有抽象方法,JDK8有默认方法和静态方法,JDK9有私有方法,无构造方法。3.设计思想:抽象类是模板设计,描述一类事物的共性特征;接口是行为规范,描述一类事物具备的能力。4.使用场景:需要复用代码、定义通用模板用抽象类;需要定义行为标准、解耦扩展用接口。三、Java集合面试题(高频重点)1.ArrayList和LinkedList的区别?标准答案:1.底层结构:ArrayList底层是动态数组;LinkedList底层是双向链表。2.查询效率:ArrayList支持随机访问,通过下标直接定位元素,查询速度极快;LinkedList只能从头节点或尾节点遍历查找,查询效率极低。3.增删效率:ArrayList增删元素会涉及数组扩容、元素移位,效率低;LinkedList增删只需要修改节点指针,无需移动元素,首尾增删效率极高。4.内存占用:ArrayList会预留冗余容量,存在内存浪费;LinkedList每个节点都要存储前后指针,单个元素占用内存更大。开发规范:绝大多数业务查询多、增删少,优先用ArrayList;频繁首尾增删、极少查询的场景用LinkedList。2.HashMap的底层原理?JDK1.7和1.8的区别?标准答案:HashMap底层是数组+链表+红黑树,基于哈希表实现,用于存储键值对数据,允许null键和null值,线程不安全。核心原理是通过key的哈希值计算数组下标,确定元素存储位置,哈希冲突时用链表解决,链表长度过长则转为红黑树优化查询效率。JDK1.7与1.8核心区别:1.底层结构:1.7是数组+单向链表;1.8新增红黑树结构,数组+链表+红黑树。2.冲突解决:1.7链表采用头插法,多线程环境下容易出现环形链表,导致死循环;1.8改为尾插法,规避了环形链表问题。3.树化阈值:链表长度超过8且数组容量大于64时,链表转为红黑树;红黑树节点小于6时退化为链表,大幅提升高冲突场景的查询效率。4.扩容优化:1.8优化了扩容重哈希逻辑,不需要重新计算所有元素哈希值,效率更高。3.HashMap和HashTable、ConcurrentHashMap的区别?标准答案:1.HashMap:线程不安全,允许null键null值,效率最高,适合单线程场景。2.HashTable:线程安全,所有方法加全局锁,效率极低,不允许null键null值,基本已被淘汰。3.ConcurrentHashMap:线程安全,是HashMap的并发优化版本。JDK1.7采用分段锁,细化锁粒度;JDK1.8采用CAS+synchronized锁,只锁当前链表/树的头节点,并发效率极高,是多线程存储键值对的首选。四、多线程面试题1.线程和进程的区别?标准答案:进程是操作系统资源分配的最小单位,线程是CPU调度的最小单位。一个进程包含多个线程,线程共享进程的堆内存和方法区资源,每个线程有自己独立的栈内存和程序计数器。进程之间相互独立,资源不共享,切换开销大;线程共享进程资源,切换开销极小,并发性能更好。Java程序默认有主线程、垃圾回收线程等多个线程。2.synchronized和Lock的区别?标准答案:1.锁类型:synchronized是JVM原生内置锁,隐式锁,自动加锁、自动释放锁;Lock是Java代码层面的显式锁,需要手动lock()加锁、unlock()释放锁。2.灵活性:Lock功能更强大,支持可中断锁、超时锁、读写锁,可以解决死锁问题;synchronized无法中断、无法设置超时,灵活性差。3.性能:JDK1.6之后synchronized做了大量优化(偏向锁、轻量级锁、重量级锁),性能和Lock基本持平,低并发场景synchronized更简洁。4.适用场景:简单同步场景用synchronized;需要精细化控制锁、读写分离、超时释放的场景用Lock。3.什么是线程死锁?如何避免?标准答案:死锁是多个线程互相持有对方需要的锁,同时互相等待对方释放锁,导致所有线程永久阻塞,程序卡死。死锁产生的四个必要条件:互斥条件、请求与保持条件、不可剥夺条件、循环等待条件。四个条件同时满足才会产生死锁。避免方案:破坏任意一个必要条件即可,最常用的是统一锁的获取顺序、设置锁超时时间、使用tryLock尝试获取锁,杜绝循环等待。五、JVM核心面试题1.JVM内存区域划分?各区域作用?标准答案:JVM运行时数据区分为线程私有区和线程共享区:线程私有(随线程启停):1.虚拟机栈:存储方法栈帧、局部变量、方法返回值,方法调用和执行都在这里,栈内存溢出会报StackOverflowError。2.本地方法栈:用于执行native本地方法,功能和虚拟机栈类似。3.程序计数器:记录当前线程执行的字节码行号,是唯一一个没有内存溢出的区域。线程共享(全局常驻):1.堆内存:所有对象、数组都在堆中分配,是垃圾回收的核心区域,也是最容易发生OOM的区域。2.方法区(元空间):存储类信息、常量、静态变量、即时编译代码等,JDK1.8后用元空间替代永久代,使用本地内存,缓解了永久代OOM问题。2.垃圾回收机制GC,哪些对象会被回收?标准答案:GC的核心是回收堆内存中没有任何有效引用的对象,释放空闲内存,避免内存泄漏。判断对象可回收的核心算法是可达性分析:以GCRoots为起始节点遍历引用链,无法遍历到的对象就是无用对象,会被GC回收。常见GCRoots:虚拟机栈中引用的对象、静态变量引用的对象、常量引用对象、本地方法栈引用对象。3.年轻代、老年代、永久代区别?标准答案:堆内存分为年轻代和老年代:1.年轻代:存放新建对象,对象存活时间短、回收频繁,分为Eden区、From、To幸存者区,大部分对象创建后很快会被MinorGC回收。2.老年代:存放存活时间久、大体积对象,经过多次GC依然存活的对象会晋升到老年代,GC频率低,触发MajorGC速度慢。3.永久代/元空间:不属于堆内存,JDK1.7及之前是永久代,存储类元数据;JDK1.8彻底废弃永久代,改用元空间,使用操作系统本地内存,容量更大,基本不会溢出。六、异常、IO、新特性面试题1.受检异常和非受检异常的区别?标准答案:1.受检异常(编译期异常):继承自Exception,不捕获、不声明抛出的话程序编译报错,必须手动处理,比如IOException、SQLException。2.非受检异常(运行期异常):继承自RuntimeException,编译不报错,运行时才会抛出,无需手动捕获,比如空指针、数组越界、类型转换异常,大多是代码逻辑问题导致。3.错误Error:系统级严重问题,无法处理,比如内存溢出、栈溢出

温馨提示

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

评论

0/150

提交评论