维创信息 Java开发工程师 一面
1. Java中自动装箱时,Integer.valueOf(127)和Integer.valueOf(128)有何区别?
思路
核心围绕Integer缓存池(IntegerCache)的范围展开,明确缓存命中与新建对象的差异。
回答示例
两者的核心区别在于是否命中Integer缓存池:
- Integer.valueOf(127):127在IntegerCache的默认缓存范围(-128~127)内,直接返回缓存池中已创建的Integer对象,不会新建实例;
- Integer.valueOf(128):128超出缓存范围,会通过
new Integer(128)创建全新的Integer对象。
补充:自动装箱(如Integer a = 127)本质就是调用Integer.valueOf(),因此Integer a=127; Integer b=127指向同一对象,而Integer c=128; Integer d=128指向不同对象。
2. 接口与抽象类在设计层面的核心差异?
思路
从“设计目的、继承限制、成员特性、多态实现”四个核心维度对比,突出接口的“行为规范”和抽象类的“模板复用”。
回答示例
接口和抽象类的核心设计差异体现在“职责定位”:
维度 |
接口 |
抽象类 |
设计目的 |
定义行为规范(能做什么),解耦实现 |
定义模板骨架(怎么做),复用代码逻辑 |
继承限制 |
类可实现多个接口(多继承) |
类只能继承一个抽象类(单继承) |
成员特性 |
JDK8+可含默认方法/静态方法,变量默认public static final |
可含普通方法/抽象方法,变量无强制修饰符(可私有/保护) |
构造器 |
无 |
有(供子类调用) |
适用场景 |
跨类统一行为(如Serializable) |
同体系类复用逻辑(如AbstractList) |
核心总结:接口是“行为契约”,抽象类是“代码复用模板”。
3. HashSet添加元素时,hashCode()和equals()的调用顺序?
思路
明确“先hashCode()判哈希值,再equals()判内容”的核心逻辑,解释哈希值的“快速筛选”作用。
回答示例
HashSet底层依赖HashMap实现,添加元素时调用顺序严格遵循:
- 先调用元素的
hashCode(),计算哈希值,定位到HashMap的对应桶位置; - 若该桶为空,直接添加元素,不调用equals();
- 若该桶已有元素,依次对比桶内元素的哈希值:
核心逻辑:hashCode()是“快速筛选器”,减少equals()的调用次数(因为equals()比hashCode()耗时)。
4. ConcurrentHashMap在JDK1.7中如何通过分段锁提升并发度?
思路
围绕“Segment分段、锁粒度降级”展开,对比HashMap的全局锁说明并发优化原理。
回答示例
JDK1.7的ConcurrentHashMap通过分段锁(Segment) 提升并发度,核心逻辑:
- 数据结构:将整个哈希表划分为多个Segment(默认16个),每个Segment本质是一个独立的HashMap;
- 锁粒度:给每个Segment加一把ReentrantLock,而非给整个哈希表加全局锁;
- 并发逻辑:
- 并发度:默认支持16个线程同时操作不同Segment,并发度远高于HashMap的全局锁(仅1个线程操作)。
补充:JDK1.8已废弃Segment,改用CAS+Synchronized(锁桶节点),进一步降低锁粒度。
5. 线程池提交任务时,核心线程未满、队列未满、最大线程未满的执行逻辑?
思路
按“核心线程→队列→最大线程”的优先级梳理执行流
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏
查看3道真题和解析