100道Java经典面试题及详细答案_第1页
100道Java经典面试题及详细答案_第2页
100道Java经典面试题及详细答案_第3页
100道Java经典面试题及详细答案_第4页
100道Java经典面试题及详细答案_第5页
已阅读5页,还剩8页未读, 继续免费阅读

下载本文档

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

文档简介

100道Java经典面试题及详细答案一、Java基础语法(1-20题)1、Java基本数据类型有哪些?区别是什么?Java有8种基本数据类型,分为四类:整型:byte(1字节)、short(2字节)、int(4字节)、long(8字节)浮点型:float(4字节)、double(8字节)字符型:char(2字节)布尔型:boolean(1字节)核心区别:基本类型直接存储数值,存放在栈内存;包装类是对象,存放在堆内存,支持泛型、为空值。浮点类型默认是double,定义float必须加f后缀,long类型建议加L后缀。2、==和equals的区别?==是比较运算符:基本类型比较数值是否相等,引用类型比较对象的内存地址是否相同。equals是Object类方法:默认和==效果一致,重写后比较对象的内容是否相等。String、Integer等常用类都重写了equals方法,只比对内容。3、String、StringBuilder、StringBuffer的区别?String:不可变字符串,每次修改都会生成新对象,适合少量字符串操作,线程安全。StringBuilder:可变字符串,线程不安全,效率高,适合单线程大量字符串拼接。StringBuffer:可变字符串,方法加了synchronized锁,线程安全,效率低,适合多线程字符串操作。4、final、finally、finalize的区别?final:修饰符,修饰类不可被继承,修饰方法不可重写,修饰变量不可修改(常量)。finally:异常处理关键字,搭配try-catch使用,代码块一定会执行(除JVM退出等极端情况),用于释放资源。finalize:Object类废弃方法,JVM垃圾回收前调用,无法保证执行时机,现已基本废弃不推荐使用。5、接口和抽象类的区别?抽象类:有构造方法,可包含普通成员变量、抽象方法和普通方法,单继承,权限可以是private、protected、public。接口:无构造方法,JDK8前只有抽象方法和常量,JDK8支持默认方法、静态方法,JDK9支持私有方法,多实现,权限默认public。核心用途:抽象类用于抽取子类通用属性和行为;接口用于定义行为规范,实现解耦。6、重载和重写的区别?重载:发生在同一个类中,方法名相同,参数列表(个数、类型、顺序)不同,和返回值、权限无关,编译期多态。重写:发生在父子类中,方法名、参数列表、返回值完全一致,权限大于等于父类,不能抛出更宽泛的异常,运行期多态。7、Java中的值传递和引用传递?Java只有值传递,没有引用传递。基本类型:传递的是变量的数值副本,方法内修改不影响原变量。引用类型:传递的是对象的地址副本,方法内修改对象内容会影响原对象,修改地址不会影响原变量。8、instanceof关键字作用?用于判断对象是否为某个类、接口的实例,返回布尔值。可以避免类型转换异常,向下转型前必须先做instanceof判断。9、Java自动装箱和拆箱?装箱:基本类型自动转为包装类对象,如int转Integer。拆箱:包装类对象自动转为基本类型,如Integer转int。缓存机制:Integer缓存-128~127范围内数值,这个区间内的对象复用,超出区间新建对象。10、Stringstr=newString("abc")创建几个对象?两个。首先在字符串常量池创建"abc"对象,再通过new在堆内存创建一个新的String对象,str指向堆内存对象。若常量池已有该字符串,则只创建一个堆对象。11、静态变量和实例变量的区别?静态变量:被static修饰,属于类,类加载时初始化,全局唯一,所有对象共享,可通过类名直接访问,存放在方法区。实例变量:无static修饰,属于对象,创建对象时初始化,每个对象独立拥有,只能通过对象访问,存放在堆内存。12、静态方法和普通方法的区别?静态方法属于类,加载即存在,可直接调用,不能访问实例变量和实例方法,没有this、super关键字。普通方法属于对象,必须创建对象才能调用,可以访问所有静态和实例资源,包含this、super。13、this和super的区别?this:代表当前对象实例,调用本类属性、方法、构造器,区分成员变量和局部变量。super:代表父类对象实例,调用父类属性、方法、构造器,用于子类访问父类资源。14、Java构造方法特点?方法名和类名完全一致,无返回值类型,创建对象时自动调用,可重载。若类中无自定义构造方法,编译器自动生成无参空构造;自定义后默认构造失效。15、volatile关键字作用(基础认知)?保证变量可见性、禁止指令重排,不保证原子性。多线程中,一个线程修改volatile变量,其他线程能立即感知最新值。16、transient关键字作用?修饰的成员变量不参与序列化,对象序列化时该变量值会被忽略,反序列化后为默认值。17、strictfp关键字作用?保证浮点运算在所有硬件平台上结果一致,避免不同设备浮点精度差异导致计算结果不同,日常开发极少使用。18、Java位运算符有哪些?与&、或|、异或^、非~、左移<<、右移>>、无符号右移>>>。左移等价乘2,右移等价除2,效率高于算术运算。19、break、continue、return的区别?break:跳出当前循环或switch语句。continue:跳过本次循环,直接进入下一次循环。return:结束当前方法,返回结果或终止方法执行。20、Java标识符命名规则?由字母、数字、下划线、$组成,不能以数字开头,不能是关键字,区分大小写。规范:类名大驼峰,方法、变量小驼峰,常量全大写下划线分隔。二、异常体系(21-30题)21、Java异常分类?所有异常父类是Throwable,分为Error和Exception。Error:系统级严重错误,如OOM、栈溢出,无需处理,程序直接崩溃。Exception:可处理异常,分为编译时异常(受检异常)和运行时异常(非受检异常)。22、编译时异常和运行时异常区别?编译时异常:继承Exception,必须手动try-catch或throws抛出,否则编译报错,如IO异常、文件不存在异常。运行时异常:继承RuntimeException,无需主动处理,运行时才会报错,如空指针、数组越界、类型转换异常。23、try-catch-finally执行顺序?先执行try代码块,出现异常匹配对应catch,最后执行finally。即便try、catch中有return,finally仍会执行。仅JVM退出、线程终止时finally不会执行。24、throw和throws的区别?throw:方法内部手动抛出单个异常对象,主动触发异常。throws:方法声明上抛出多个异常,告知调用者处理异常,被动声明。25、常见运行时异常有哪些?NullPointerException空指针、ArrayIndexOutOfBoundsException数组越界、ClassCastException类型转换异常、IllegalArgumentException参数非法异常、ArithmeticException算术异常。26、自定义异常如何实现?继承Exception(编译异常)或RuntimeException(运行异常),重写无参、有参构造方法,用于业务场景精准异常提示。27、finally块为什么不能省略?核心作用?不是必须写,try-catch可单独使用。核心作用是释放资源,如关闭流、数据库连接、释放锁,保证资源一定会回收。28、try里有return,finally还执行吗?会执行。return执行前会先执行finally代码块,再返回结果。如果finally中也有return,会覆盖之前的返回值,开发中禁止在finally写return。29、异常链是什么?捕获一个异常后抛出另一个新异常,并保留原始异常信息,方便排查完整报错链路,通过initCause()实现异常溯源。30、Java异常处理最佳实践?精准捕获异常,不捕获最大的Exception;不忽略异常,必须打印日志;业务异常自定义区分系统异常;finally统一释放资源;禁止滥用try-catch掩盖bug。三、集合框架(31-50题)31、集合和数组的区别?数组长度固定,集合长度可变;数组可存基本类型和对象,集合只能存对象;数组功能单一,集合提供增删改查、遍历、排序等丰富方法。32、List、Set、Map的区别?List:有序可重复,索引访问,常用ArrayList、LinkedList。Set:无序不可重复,无索引,常用HashSet、TreeSet。Map:键值对存储,键唯一值可重复,无序,常用HashMap、TreeMap。33、ArrayList和LinkedList区别?底层结构:ArrayList基于动态数组,LinkedList基于双向链表。查询:ArrayList随机访问快,支持索引查找;LinkedList查询慢,需遍历。增删:ArrayList末尾增删快,中间增删需移动元素;LinkedList任意位置增删快。内存:ArrayList连续内存,有扩容冗余;LinkedList每个节点存指针,内存占用高。34、ArrayList扩容机制?初始容量10,JDK1.7后懒加载,首次添加元素初始化容量。每次扩容为原容量的1.5倍,扩容后复制原数组元素到新数组,耗时较高,大数据量可手动指定初始容量。35、HashMap底层原理?(高频)JDK1.8底层是数组+链表+红黑树。通过hash算法计算key索引位置,哈希冲突时链表存储,链表长度超过8且数组容量大于64,转为红黑树;红黑树节点少于6,转回链表。默认容量16,负载因子0.75,扩容翻倍。36、HashMap为什么线程不安全?多线程put时会出现数据覆盖、链表环形、数据丢失问题。JDK1.7扩容易产生循环链表死循环,JDK1.8解决死循环,但仍存在数据覆盖问题,并发场景推荐ConcurrentHashMap。37、HashMap和HashTable区别?线程安全:HashTable线程安全(方法加锁),HashMap不安全。键值null:HashMap允许一个key为null、多个value为null;HashTable不允许null键值。效率:HashMap效率高,HashTable全表锁效率极低,基本淘汰。38、ConcurrentHashMap原理?JDK1.8采用CAS+synchronized锁,锁住单个链表/树节点,粒度极小,并发效率高。底层同样是数组+链表+红黑树,支持高并发读写,线程安全且性能优异。39、HashSet去重原理?HashSet底层基于HashMap实现,存储元素时调用hashCode()计算哈希值,再调用equals()比对内容,两者都相同判定为重复元素,拒绝存储。40、为什么重写equals必须重写hashCode?若只重写equals不重写hashCode,两个内容相同的对象,哈希值可能不同,会导致HashSet、HashMap无法正确去重,出现重复存储问题。规范:相等的对象必须哈希值相等。41、TreeSet和TreeMap特点?底层基于红黑树,可实现元素自然排序或自定义排序,线程不安全,查询、增删效率稳定。42、LinkedHashMap特点?继承HashMap,底层维护双向链表,保留元素插入顺序或访问顺序,可实现LRU缓存淘汰策略。43、Vector和ArrayList区别?Vector线程安全(方法加锁),效率低,扩容2倍;ArrayList线程不安全,效率高,扩容1.5倍,日常开发优先用ArrayList。44、集合遍历方式有哪些?普通for循环、增强for循环、迭代器Iterator、Lambda流式遍历。遍历时删除元素推荐用迭代器,避免并发修改异常。45、并发修改异常产生原因?迭代器遍历集合时,通过集合自身方法增删元素,破坏迭代器一致性校验,触发ConcurrentModificationException。解决方式:迭代器remove、使用并发集合。46、HashMap负载因子0.75的原因?平衡空间利用率和查询效率。负载因子过小,扩容频繁、空间浪费;过大,哈希冲突增多、链表变长,查询效率下降,0.75是最优折中值。47、HashMap树化阈值为什么是8?链表节点少时,遍历效率高于红黑树;节点过多,链表查询效率骤降。统计显示链表长度达到8的概率极低,树化可大幅提升查询性能,同时避免频繁转换结构。48、Collections和Collection区别?Collection:集合顶层接口,包含List、Set子接口。Collections:集合工具类,提供静态方法实现集合排序、同步、空集合创建等功能。49、什么是fail-fast和fail-safe?fail-fast:快速失败,普通集合遍历修改立即抛异常,如ArrayList、HashMap。fail-safe:安全失败,并发集合遍历基于快照,修改不影响遍历,不抛异常,如ConcurrentHashMap,遍历数据可能非最新。50、Java流式编程Stream特点?用于集合、数组数据处理,支持链式编程,分为中间操作(延迟执行)和终止操作(触发执行),不修改原数据,适合复杂数据筛选、排序、聚合统计。四、多线程(51-70题)51、线程和进程的区别?进程:系统资源分配的最小单位,独立内存,进程间互不干扰,开销大。线程:CPU调度的最小单位,共享进程内存资源,切换开销小,是进程的执行单元。52、Java实现多线程的方式?继承Thread类、实现Runnable接口、实现Callable接口(带返回值、可抛异常)、线程池创建线程。推荐用Runnable和线程池,避免单继承限制,统一管理线程。53、start()和run()区别?start():启动线程,由JVM调用run()方法,开启新线程,只能调用一次。run():普通方法调用,直接执行不会开启新线程,可重复调用。54、线程的生命周期?新建、就绪、运行、阻塞、终止五种状态。阻塞分为等待阻塞、同步阻塞、超时阻塞。55、sleep()和wait()区别?所属类:sleep是Thread方法,wait是Object方法。锁释放:sleep不释放锁,wait释放锁。唤醒方式:sleep超时自动唤醒,wait需手动notify/notifyAll唤醒。使用场景:任意场景用sleep,同步代码块内用wait。56、notify和notifyAll区别?notify:随机唤醒一个等待线程。notifyAll:唤醒所有等待线程,竞争锁资源,避免线程饿死,开发优先用notifyAll。57、synchronized和Lock区别?synchronized:内置锁,自动加锁释放锁,适合少量并发场景,可锁方法、代码块,底层依赖JVM实现。Lock:手动锁(ReentrantLock),需手动lock()加锁、unlock()释放锁,支持可中断锁、公平锁、超时锁,功能更丰富,高并发性能更好。58、volatile能否保证线程安全?不能。volatile只保证可见性、有序性,不保证原子性。复合操作(i++)依旧线程不安全,需配合锁保证安全。59、什么是原子类?原理?java.util.concurrent.atomic包下工具类,如AtomicInteger,基于CAS无锁机制实现线程安全,比锁效率高,适合简单数值更新场景。60、CAS原理及优缺点?CAS即比较并交换,无锁乐观锁机制:比较内存值和预期值,一致则更新,失败重试。优点:无锁、效率高;缺点:自旋消耗CPU、存在ABA问题、只能保证单个变量原子性。61、ABA问题如何解决?线程修改变量时,其他线程先改B再改回A,CAS无法识别。解决方式:使用带版本号的原子类AtomicStampedReference,通过版本号区分修改记录。62、线程池核心参数?核心线程数、最大线程数、空闲线程存活时间、时间单位、任务队列、线程工厂、拒绝策略。63、线程池拒绝策略有哪些?默认四种:丢弃任务抛异常、丢弃队列最旧任务、直接丢弃当前任务、调用者线程执行任务。可自定义拒绝策略适配业务。64、为什么不推荐使用Executors创建线程池?FixedThreadPool、SingleThreadPool队列无界,可能堆积大量任务导致OOM;CachedThreadPool最大线程数无限制,可能创建大量线程耗尽CPU资源。生产环境必须手动自定义线程池。65、线程死锁产生条件及解决?四大必要条件:互斥、请求保持、不可剥夺、循环等待。解决:破坏循环等待条件,统一锁的获取顺序、设置锁超时、避免嵌套锁。66、CountDownLatch、CyclicBarrier、Semaphore区别?CountDownLatch:倒计时计数器,一次性使用,主线程等待子线程完成。CyclicBarrier:循环栅栏,可重复使用,多个线程互相等待集齐后统一执行。Semaphore:信号量,控制并发线程数量,做限流、资源抢占。67、ThreadLocal原理及场景?线程本地变量,每个线程独有一份变量副本,线程间隔离。底层基于ThreadLocalMap存储,常用于存储用户登录信息、数据库连接,避免参数传递。68、ThreadLocal内存泄漏原因?ThreadLocalMap的key是弱引用,value是强引用。线程长期存活(线程池),key被回收后value无法回收,导致内存泄漏。使用后必须手动remove()清除。69、公平锁和非公平锁区别?公平锁:线程按请求顺序获取锁,无线程饿死,吞吐量低。非公平锁:线程抢占锁,可能插队,吞吐量高,默认锁都是非公平锁。70、可重入锁是什么?同一线程可多次获取同一把锁,避免自身阻塞死锁。synchronized和ReentrantLock都是可重入锁。五、JVM原理(71-80题)71、JVM内存区域划分?程序计数器、虚拟机栈、本地方法栈、堆、方法区(元空间)。其中堆和方法区是线程共享,其余为线程私有。72、各内存区域作用?程序计数器:记录当前线程执行字节码行号,无OOM。虚拟机栈:存储局部变量、方法栈帧,方法执行创建,结束销毁。堆:存放所有对象实例和数组,GC主要回收区域。方法区:存储类信息、常量、静态变量、编译后的代码。73、堆内存分区?新生代(Eden、From、To)、老年代。新生代存放新创建对象,老年代存放存活久、大对象。74、MinorGC、MajorGC、FullGC区别?MinorGC:新生代垃圾回收,频率高、速度快。MajorGC:老年代垃圾回收,频率低、速度慢。FullGC:整堆回收(新生代+老年代+元空间),耗时最长,尽量避免。75、对象创建及分配流程?类加载校验→分配内存(指针碰撞/空闲列表)→初始化零值→设置对象头→执行init方法。优先分配Eden区,大对象直接进入老年代。76、对象存活判定方式?引用计数法(存在循环引用问题,JVM不采用)、可达性分析法(从GCRoots遍历,不可达对象判定为垃圾)。77、GCRoots包含哪些?虚拟机栈局部变量引用对象、本地方法栈JNI引用对象、方法区静态变量/常量引用对象、活跃线程对象。78、垃圾回收算法有哪些?标记清除:速度快,产生内存碎片。标记整理:无碎片,速度慢。复制算法:无碎片,适合新生代,浪费一半空间。79、常见垃圾收集器?新生代:Serial、ParNew、ParallelScavenge。老年代:SerialOld、ParallelOld、CMS。整堆:G1、ZGC、Shenandoah(低延迟收集器)。80、类加载过程?加载、验证、准备、解析、初始化。加载读取class文件生成Class对象;验证保证字节码合法;准备初始化静态变量默认值;解析替换符号引用;初始化执行静态代码块和静态变量赋值。六、IO、泛型、注解(81-90题)BIO:同步阻塞,一个连接一个线程,并发低。NIO:同步非阻塞,缓冲区+通道+选择器,单线程处理多连接,高并发常用。82、NIO三大核心组件?Buffer缓冲区:存储读写数据。Channel通道:数据传输通道,双向读写。Selector选择器:监听多个通道事件,实现多路复用。83、字节流和字符流区别?字节流:处理所有文件(图片、视频、文本),以字节为单位,无缓冲区。字符流:仅处理文本文件,以字符为单位,自带缓冲区,需刷新或关闭流写入数据。84、序列化和反序列化?序列化:对象转字节流,用于网络传输、持久化存储。反序列化:字节流转对象,恢复数据。类需实现Serializable接口,版本号serialVersionUID保证兼容。85、泛型的作用?编译期类型检查,避免类型转换异常;省去强制类型转换代码;实现代码通用复用,提升代码安全性和复用性。86、泛型通配符?、?extends、?super区别??:任意类型。?extendsT:上界通配符,只能读不能写。?superT:下界通配符,只能写不能读。87、泛型为什么不能用基本类型?泛型编译后会类型擦除,最终转为Object类型,基本类型无法向上转型为Object,只能使用包装类。88、注解的作用?标记代码、配置信息,编译期或运行期通过反射获取注解信息,简化配置、实现框架功能(如Spring注解)。89、元注解有哪些?@Target:指定注解作用位置(类、方法、字段等)。@Retention:指定注解生命周期(源码、编译、运行)。@Documented:生成文档保留注解。@Inherited:子类可继

温馨提示

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

评论

0/150

提交评论