Java 中级工程师面试题(真实企业场景版)_第1页
Java 中级工程师面试题(真实企业场景版)_第2页
Java 中级工程师面试题(真实企业场景版)_第3页
Java 中级工程师面试题(真实企业场景版)_第4页
Java 中级工程师面试题(真实企业场景版)_第5页
已阅读5页,还剩2页未读, 继续免费阅读

下载本文档

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

文档简介

Java中级工程师面试题(真实企业场景版)说明:本套题目适配1-3年Java开发工程师中级岗位,贴合互联网、传统软件企业真实面试提问风格,侧重实战原理、踩坑经验、场景落地,无理论空话,涵盖Java基础、集合、多线程、JVM、框架、数据库、实战优化七大核心模块,附带详细标准答案。一、Java基础核心(高频必问)1.说说==和equals的区别?String类的equals是如何实现的?参考答案:==是运算符,对于基本数据类型,比较的是数值是否相等;对于引用类型,比较的是对象的内存地址是否相同。equals是Object类的方法,默认实现和==一致,比较对象地址。大部分业务类(String、Integer)会重写该方法,重写后用于比较对象的内容是否相等。String重写的equals逻辑:先判断两个对象地址是否相同,相同直接返回true;再判断是否为String类型,最后逐位比较字符内容,全部一致则返回true。2.String、StringBuilder、StringBuffer的区别?日常开发如何选择?参考答案:1、可变性:String是不可变字符串,底层为final字符数组,每次拼接都会生成新对象;StringBuilder、StringBuffer是可变字符串,直接修改底层字符数组,不会频繁创建新对象。2、线程安全:StringBuffer所有方法加了synchronized锁,线程安全,效率低;StringBuilder无锁,线程不安全,效率高。3、使用场景:少量字符串拼接用String;单线程大量拼接用StringBuilder;多线程环境字符串拼接用StringBuffer。3.final、finally、finalize的区别?参考答案:final是修饰符,可修饰类、方法、变量:修饰类不可被继承,修饰方法不可被重写,修饰变量为常量,只能赋值一次。finally是异常处理关键字,搭配try-catch使用,代码块中的代码无论是否抛出异常、是否return,都会执行(唯一不执行场景:调用System.exit(0))。finalize是Object类的废弃方法,JDK9之后废弃,原本用于垃圾回收前对象的资源释放,无法保证执行时机,业务开发基本不用。4.接口和抽象类的区别?什么场景下用抽象类?参考答案:1、定义:抽象类用abstract修饰,可包含普通方法、抽象方法、成员变量、构造方法;接口(JDK8前)只能有抽象方法和常量,JDK8支持默认方法、静态方法,JDK9支持私有方法。2、继承:类只能单继承抽象类,但可以多实现接口。3、构造方法:抽象类有构造方法,用于子类初始化;接口无构造方法。4、使用场景:需要抽取子类通用属性、通用代码、实现代码复用,用抽象类;只需要定义行为规范、做功能扩展、解耦,用接口。二、Java集合框架(面试重点)1.ArrayList和LinkedList的区别?随机访问和新增删除谁更快?为什么?参考答案:ArrayList底层是动态数组,支持下标随机访问,查询速度极快;数组扩容、中间插入/删除元素需要移动大量元素,增删效率低。LinkedList底层是双向链表,无下标,不支持随机访问,只能遍历查找,查询效率低;新增、删除只需要修改节点指针,无需移动元素,首尾增删效率极高。日常开发:查询多、增删少用ArrayList;频繁首尾增删、少量查询用LinkedList。2.HashMap的底层原理?JDK1.7和JDK1.8的核心区别?参考答案:HashMap底层基于「数组+链表/红黑树」实现,通过hash算法计算元素下标,解决hash冲突后存储键值对,默认负载因子0.75,初始容量16。核心区别:1、数据结构:JDK1.7是数组+单向链表;JDK1.8是数组+单向链表+红黑树,链表长度大于8、数组容量大于64时,链表转为红黑树,优化查询效率。2、插入方式:1.7头插法,多线程扩容易出现环形链表死循环;1.8尾插法,规避了环形链表问题。3、扩容机制:1.7扩容后重新计算hash位置;1.8优化hash迁移逻辑,部分元素无需重新计算hash,直接保留原下标或偏移16位。3.HashMap为什么线程不安全?工作中如何解决并发场景的Map问题?参考答案:HashMap线程不安全核心场景:多线程同时put数据会导致数据覆盖;JDK1.7多线程扩容会产生环形链表,触发死循环、CPU飙升。并发解决方案:1、低并发:使用Collections.synchronizedMap,基于同步代码块实现,整体加锁,效率一般。2、高并发:使用ConcurrentHashMap,JDK1.8基于CAS+synchronized分段锁,锁粒度细化,并发性能极高,是企业主流选择。4.HashSet的底层实现原理?为什么存储对象必须重写hashCode和equals?参考答案:HashSet底层直接复用HashMap,存储的元素作为HashMap的key,value为固定的空常量对象。去重原理:新增元素先调用hashCode计算哈希值确定存储位置,哈希值相同再调用equals比较内容。如果只重写equals不重写hashCode,会导致相同内容对象哈希值不同,重复存储;只重写hashCode不重写equals,会导致不同对象哈希值一致,被误判为重复,因此必须同时重写两个方法。三、多线程与并发(中级核心难点)1.线程的生命周期有哪些状态?wait和sleep的核心区别?参考答案:线程五大核心状态:新建、就绪、运行、阻塞、终止。wait和sleep区别:1、所属类:wait是Object类方法;sleep是Thread类静态方法。2、锁释放:wait会释放当前持有的锁;sleep只会休眠线程,不会释放锁。3、唤醒方式:wait可被notify/notifyAll主动唤醒,或超时唤醒;sleep只能超时自动唤醒。4、使用场景:wait必须在同步代码块/同步方法中使用;sleep可任意场景使用。2.synchronized和Lock的区别?日常开发怎么选型?参考答案:1、锁类型:synchronized是内置锁、隐式锁,JVM底层实现;Lock是接口锁、显式锁,代码层面实现(常用ReentrantLock)。2、锁特性:synchronized无法中断、无法超时、非公平锁;ReentrantLock支持可中断、超时锁、公平锁、可绑定多个条件队列。3、释放方式:synchronized代码执行完毕或异常自动释放锁;Lock必须手动调用unlock释放,否则会死锁。选型:简单同步场景、代码量小用synchronized(JDK1.6后优化后性能持平Lock);需要超时锁、可中断锁、公平锁、精细化锁控制,用ReentrantLock。3.什么是线程池?为什么不推荐手动newThread?核心参数有哪些?参考答案:线程池是统一管理线程的容器,可复用线程、控制并发数、避免频繁创建销毁线程的资源消耗。不推荐手动newThread的原因:频繁创建销毁线程开销大、无统一管控、并发不可控、容易OOM、任务堆积无法处理。线程池七大核心参数:核心线程数、最大线程数、空闲超时时间、时间单位、任务队列、线程工厂、拒绝策略。日常开发禁止使用Executors创建线程池,必须手动通过ThreadPoolExecutor自定义参数,规避资源耗尽风险。4.谈谈你对CAS的理解?存在什么问题?参考答案:CAS是无锁乐观锁机制,全称比较并交换,操作逻辑:获取内存原值、比较当前值和内存值、一致则更新,不一致则重试。优点:无锁阻塞,并发性能远高于重量级锁。存在问题:循环重试消耗CPU、只能保证单个变量原子性、存在ABA问题(可通过版本号机制解决)。四、JVM与性能调优(中级必备)1.JVM内存区域划分?哪些是线程私有,哪些是线程共享?参考答案:线程私有(随线程创建销毁):程序计数器、虚拟机栈、本地方法栈。线程共享(全局共享):堆内存、方法区(元空间)。核心说明:堆是所有对象实例、数组的存储区域,是GC回收的核心区域;元空间存储类信息、常量、静态变量、方法字节码。2.说说GC的种类和回收机制?G1和ZGC的区别?参考答案:GC分MinorGC(新生代回收)、MajorGC(老年代回收)、FullGC(整堆回收)。新生代常用复制算法,老年代常用标记清除、标记整理算法。G1:面向大内存、低延迟的垃圾收集器,将堆内存划分为多个分区,可预测停顿时间,适合中小型服务。ZGC:JDK11推出的低延迟收集器,支持TB级内存,停顿时间几乎可控在10ms内,比G1延迟更低、吞吐量更高,适合高并发、低延迟核心服务。3.常见的OOM异常有哪些?工作中如何排查OOM问题?参考答案:常见OOM类型:堆内存溢出、元空间溢出、线程栈溢出、直接内存溢出。排查步骤:1、导出堆快照dump文件;2、使用MAT、JProfiler分析大对象、泄漏对象;3、定位代码中的集合未清空、静态变量常驻内存、循环创建对象等问题;4、修复代码并调整JVM参数。五、Spring框架核心(业务开发高频)1.Spring的IOC和AOP原理?说说你的理解和实战使用场景参考答案:IOC控制反转:将对象的创建、初始化、依赖管理交给Spring容器,无需手动new对象,实现组件解耦,核心是依赖注入(DI)。常用注入方式:构造器注入、setter注入、注解注入,官方推荐构造器注入。AOP面向切面编程:基于动态代理机制,在不修改原有业务代码的前提下,对方法进行增强。核心原理:JDK动态代理(接口代理)、CGLIB代理(类代理)。实战场景:日志记录、权限校验、事务控制、接口限流、性能监控、统一异常处理。2.SpringBean的生命周期?单例Bean是线程安全的吗?参考答案:Bean完整生命周期:实例化->属性填充->前置处理->初始化方法->后置处理->放入单例池->容器销毁时执行销毁方法。Spring默认单例Bean非线程安全。单例Bean全局共享,多个线程同时操作Bean的成员变量会出现数据覆盖、并发问题。解决方案:尽量不要定义成员变量,使用ThreadLocal存储线程私有数据,或将Bean改为多例。3.Spring事务的传播机制和隔离级别?日常踩过什么事务坑?参考答案:七大传播机制:常用REQUIRED(默认)、SUPPORTS、REQUIRES_NEW、NESTED,核心掌握REQUIRED(有事务加入,无则新建)、REQUIRES_NEW(独立事务,互不影响)。四大隔离级别:读未提交、读已提交、可重复读、串行化,MySQL默认可重复读。常见事务坑:1、同类中方法内部调用,事务失效(AOP动态代理失效);2、try-catch捕获异常,事务无法回滚;3、非public方法事务失效;4、多线程场景下事务失效。六、数据库与MyBatis(业务实战必考)1.MySQL索引原理?B+树为什么比B树、哈希索引更适合数据库?参考答案:MySQLInnodb引擎索引底层是B+树。优势对比:B+树所有数据都在叶子节点,非叶子节点只存索引键,内存占用小、IO次数少;叶子节点有序链表,支持范围查询、排序、分页。B树每个节点都存数据,IO开销大;哈希索引不支持范围查询和排序,仅支持等值查询。2.什么是索引失效?日常开发中哪些场景会导致索引失效?参考答案:索引失效即查询没有走索引,触发全表扫描。常见场景:1、索引列使用函数、运算、类型转换;2、like以%开头模糊查询;3、or连接无索引字段;4、违反最左前缀原则;5、MySQL优化器判断全表扫描比索引更快,主动放弃索引。3.MyBatis的#{}和${}的区别?为什么禁止随意使用${}?参考答案:#{}是预编译占位符,会自动拼接参数、转义特殊字符,防止SQL注入,支持参数类型匹配,日常开发默认使用。${}是字符串直接拼接,无预编译、无转义,存在严重SQL注入风险。仅适用于动态表名、动态排序字段等无法使用预编译的场景,使用时必须手动校验参数合法性。七、实战场景与优化(区分初级/中级核心)1.接口响应慢,你排查问题的思路是什么?参考答案:1、先看日志:排查是否有异常、超时、报错;2、看数据库:检查SQL执行耗时、是否全表扫描、索引失效、慢查询;3、看代码:排查循环查库、重复查询、无缓存、死循环;4、看资源:服务器CPU、内存、磁盘IO、网络带宽;5、看中间件:Redis、MQ连接超时、阻塞、堆积;6、针对性优化:加索引、加缓存、异步化、拆分接口。2

温馨提示

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

评论

0/150

提交评论