互联网大厂 Java 面试实录:谢飞机的三轮攻防战

互联网大厂 Java 面试实录:谢飞机的三轮攻防战
互联网大厂 Java 面试实录谢飞机的三轮攻防战场景某互联网大厂终面现场。面试官表情严肃谢飞机抱着水杯坐得笔直嘴上说自己“准备得很充分”手心却全是汗。第一轮Java 核心与集合面试官先别紧张讲讲 Java 中和equals()的区别。谢飞机比较的是是不是同一个人equals()比较的是是不是同一个灵魂。比如两个new String(飞).new String(机)不行equals()就行。面试官这个回答不错说明基础还没还给老师。那hashCode()为什么要和equals()一起重写谢飞机因为……它俩是绑定套餐。你要是只重写equals()HashMap可能以为你是陌生人重写了hashCode()它才能先按门牌号找再按身份证确认。面试官行。ArrayList和LinkedList有什么区别什么场景用哪个谢飞机ArrayList像地铁查找快插入中间会挤得慌LinkedList像接力赛插入删除方便但查找得一个个问。平时大多数场景我先用ArrayList别跟内存过不去。面试官那HashMap底层为什么快JDK 8 做了什么优化谢飞机它先算hash然后定位桶位再在桶里找。JDK 8 之后链表太长会变红黑树听说这样能把“排队买奶茶”的人群变成“有秩序的排队系统”。面试官最后一个final、finally、finalize()分别是什么谢飞机final是不让你改finally是无论如何都要执行finalize()是对象临走前最后看一眼世界不过这个现在基本不推荐用了。第二轮并发、JUC、JVM 与线程池面试官好基础还行。现在说说synchronized和ReentrantLock的区别。谢飞机synchronized是 JVM 帮你上锁写法简单出了门自动解锁ReentrantLock更灵活能尝试加锁、可中断、可公平锁。一个像保安大叔一个像门禁系统。面试官那你知道volatile是干什么的吗它能保证什么不能保证什么谢飞机volatile能保证可见性线程改了值别的线程能立刻看到还能禁止部分重排序。它不能保证原子性所以i这种复合操作还是会翻车。面试官线程池为什么要用核心参数有哪些谢飞机因为线程创建和销毁都贵频繁搞会像外卖骑手每单都重新买车。线程池可以复用线程提高性能还能控制并发。面试官说说ThreadPoolExecutor的核心参数。谢飞机corePoolSize是常驻工位maximumPoolSize是最大编制workQueue是待办队列keepAliveTime是临时工待岗时间threadFactory是招人部门handler是队列满了以后怎么处理。面试官如果队列满了会怎样拒绝策略有哪些谢飞机有AbortPolicy直接报错CallerRunsPolicy让提交任务的人自己干DiscardPolicy直接扔掉DiscardOldestPolicy扔掉最老的任务。这个问题像“工位满了还要进人”总得有人背锅。面试官好。JVM 里对象什么时候进入老年代垃圾回收了解多少谢飞机对象一般先在新生代熬过几次 GC 还活着就晋升老年代。GC 有 Minor GC、Major GC、Full GC。年轻人死得快老同志更难请走。面试官那你说下类加载过程。谢飞机加载、验证、准备、解析、初始化。加载是把 class 搬进来验证是查户口准备是分配静态变量内存解析是把符号引用变成直接引用初始化才开始真正赋值。第三轮框架、中间件、数据库与工程化面试官前面还算顺。现在聊聊 Spring什么是 IOC 和 AOP谢飞机IOC 是把对象创建和依赖注入交给容器不用自己满世界new。AOP 是把日志、事务、权限这些和业务无关但到处都要用的逻辑抽出来统一织进去。面试官Spring 事务失效的场景你知道吗谢飞机大概知道一些。比如同类内部方法调用没走代理、异常被吞了、方法不是public、数据库引擎不支持事务、事务传播行为不对……反正事务就像承诺书得按规则签不能私下口头说算数。面试官MyBatis 的一级缓存和二级缓存区别是什么谢飞机一级缓存是SqlSession级别默认开启生命周期短二级缓存是Mapper级别跨会话共享得配置后才有。简单说一个是办公室抽屉一个是部门公共柜子。面试官说说 Redis 常见数据结构和缓存穿透、击穿、雪崩。谢飞机Redis 有 String、Hash、List、Set、ZSet还有 Bitmap、HyperLogLog、Geo、Stream。穿透是查不存在的数据一直打到数据库击穿是热点 key 突然失效雪崩是一大批 key 同时失效。面试官怎么解决谢飞机穿透可以用布隆过滤器、缓存空值击穿可以加互斥锁、逻辑过期雪崩可以给 key 加随机过期时间、分批预热、限流降级。面试官MySQL 索引为什么能快BTree和BTree有什么区别谢飞机索引本质是减少扫描范围。BTree的数据都在叶子节点叶子之间还有链表适合范围查询BTree不是这么典型的叶子链表结构。MySQL 常用BTree因为既能快速定位也方便顺序遍历。面试官最后Docker 你会怎么理解项目里怎么用谢飞机Docker 就是把应用和运行环境打包成镜像像把一碗面连锅一起端走到哪儿都能煮。项目里常用来统一环境、快速部署、做 CI/CD避免“我电脑上能跑”的经典甩锅。面试官好了今天先到这里。你回去等通知吧。谢飞机好的老师我回去再把“缓存三兄弟”和“线程池四件套”背熟一点争取下次别把volatile说成“高贵的变量”。面试题标准答案详解1. Java 核心和equals()比较的是引用是否相同对于基本类型比较的是值是否相同。equals()默认也是比较引用但很多类会重写它用于比较内容比如String、Integer。约定如果重写了equals()通常也要重写hashCode()否则在哈希容器中会出现逻辑不一致。hashCode()为什么和equals()配套HashMap先通过hashCode()定位桶再通过equals()比较是否为同一个键。如果两个对象equals()相等它们的hashCode()必须相等。反过来不一定hashCode()相等只能说明可能冲突。ArrayList和LinkedListArrayList基于动态数组随机访问快尾部追加通常效率高。LinkedList基于双向链表插入和删除某些场景更有优势但随机访问慢。业务上大多数情况优先ArrayList因为读多写少很常见。HashMap底层原理JDK 8 之后底层是数组 链表/红黑树。通过hash()定位数组下标冲突时用链表或红黑树存储。当链表长度超过阈值且数组容量足够大时会树化提高查找效率。扩容会触发重新分布元素因此要关注初始化容量避免频繁扩容。final、finally、finalize()final修饰变量、方法、类表示不可修改、不可重写、不可继承。finally异常处理中的代码块无论是否抛异常通常都会执行。finalize()对象被回收前可能调用的方法但不可靠已不推荐使用。2. 并发、JUC、JVMsynchronized和ReentrantLocksynchronized是 JVM 层面的内置锁语法简单自动释放锁。ReentrantLock是 JUC 提供的显式锁功能更强大。ReentrantLock支持公平锁、非公平锁、尝试加锁、可中断、条件变量等。选择上如果需求简单优先synchronized需要高级特性再用ReentrantLock。volatile保证变量对所有线程的可见性。可以防止指令重排序带来的部分问题。不能保证复合操作的原子性比如count不是线程安全的。常用于状态标识、单例双重检查中的实例引用等。为什么要用线程池避免频繁创建和销毁线程带来的开销。控制系统最大并发量防止资源耗尽。统一管理线程生命周期提高任务执行效率。ThreadPoolExecutor参数corePoolSize核心线程数常驻线程数量。maximumPoolSize最大线程数。workQueue任务队列用于缓存等待执行的任务。keepAliveTime非核心线程空闲后存活时间。threadFactory创建线程的工厂。handler拒绝策略。拒绝策略AbortPolicy直接抛异常。CallerRunsPolicy由提交任务的线程执行任务。DiscardPolicy直接丢弃任务。DiscardOldestPolicy丢弃队列中最老的任务。JVM 与垃圾回收Java 对象通常先分配在堆的新生代。对象经过多次 GC 仍存活可能晋升到老年代。Minor GC主要回收新生代Major GC或Full GC影响范围更大停顿时间也通常更长。需要根据对象生命周期特征合理设计代码减少大对象和短命对象混用带来的回收压力。类加载过程加载读取 class 文件并生成Class对象。验证确保字节码合法、安全。准备为静态变量分配内存并设置默认值。解析把符号引用替换为直接引用。初始化执行静态变量赋值和静态代码块。3. Spring、MyBatis、Redis、MySQL、DockerIOC 和 AOPIOC控制反转把对象创建和依赖管理交给容器。DI依赖注入是 IOC 的具体实现方式。AOP面向切面编程把日志、事务、权限等横切逻辑统一处理。Spring 通过代理机制实现 AOP常见有 JDK 动态代理和 CGLIB。Spring 事务失效常见原因同类内部调用未经过代理对象。异常被捕获后未继续抛出事务无法回滚。方法修饰符不符合事务要求例如非public。数据库引擎不支持事务如 MyISAM。传播行为、隔离级别配置不合理。MyBatis 一级缓存和二级缓存一级缓存SqlSession级别默认开启同一个会话内有效。二级缓存Mapper级别需要显式开启多个会话可共享。缓存适合读多写少的场景但要注意一致性问题。Redis 常见数据结构String最基础适合缓存对象、计数器。Hash适合对象字段存储。List适合队列、消息流转。Set适合去重、标签。ZSet适合排行榜、延迟队列。其他结构如Bitmap、HyperLogLog、Geo、Stream也很常见。缓存穿透、击穿、雪崩穿透查询不存在数据数据库和缓存都没有流量直接打到数据库。解决布隆过滤器、缓存空值、接口参数校验。击穿热点 key 过期瞬间大量请求打到数据库。解决互斥锁、逻辑过期、热点预热。雪崩大量 key 同时失效。解决过期时间加随机值、分批过期、限流、降级。MySQL 为什么用BTreeBTree叶子节点存储数据非叶子节点只存索引信息。叶子节点有链表范围查询和排序更高效。树高更低磁盘 IO 次数更少适合数据库场景。Docker 的核心价值把应用和依赖一起封装成镜像保证环境一致性。容器启动快、资源占用低适合微服务和自动化部署。常用于开发测试环境统一、CI/CD、快速扩缩容。4. 面试小结基础题要回答准确、简洁、抓重点。并发和 JVM 题要说明原理、风险和适用场景。框架和中间件题要结合业务场景讲清“为什么这样设计”。面试时如果不会先说出你知道的部分再补充思路比胡乱猜更稳。