奇虎360 Java开发工程师 一面

1. 基本数据类型与包装类在内存分配上有何本质差异?

思路

核心区分“栈/堆分配”“值存储/引用存储”,结合常量池补充包装类的特殊情况。

回答示例

基本数据类型和包装类的内存分配核心差异有两点:

  1. 存储位置与方式
  2. 常量池优化

包装类存在缓存池(如IntegerCache缓存-128~127),范围内的包装类对象会复用常量池中的实例(堆上),超出范围才新建对象;基本类型无此概念。

示例

int a = 10; // 栈存数值10
Integer b = 10; // 栈存引用,堆复用常量池对象
Integer c = new Integer(10); // 栈存引用,堆新建对象(不走常量池)

2. 接口中定义的静态方法能否被子接口继承?

思路

明确“不能继承”,结合Java语法规则解释原因,区分静态方法与默认方法的继承特性。

回答示例

接口中的静态方法不能被子接口继承,核心原因:

  1. Java语法规定:接口的静态方法属于当前接口本身,而非接口的实现/子接口,子接口无法继承父接口的静态方法;
  2. 调用方式:父接口静态方法必须通过“父接口名.方法名()”调用,子接口无法通过自身名称调用父接口静态方法。

示例

interface Parent {
    static void method() { System.out.println("parent"); }
}
interface Child extends Parent {}

// 正确:Parent.method()
// 错误:Child.method()(编译报错,Child未继承method)

补充:接口的default方法可被子接口继承/重写,静态方法则不行,这是静态成员“属于类/接口本身”的特性决定的。

3. finally块中修改返回值,最终返回结果以谁为准?(附代码场景)

思路

分“基本类型”和“引用类型”两种场景,结合代码示例说明核心规则:finally修改返回值时,以finally执行后的结果为准(基本类型),引用类型则看是否修改对象内部值。

回答示例

核心规则:finally块会在return之前执行,若finally中修改返回值,最终返回以finally的修改结果为准(基本类型);引用类型需区分“修改引用”和“修改对象内容”。

场景1:基本类型(finally修改返回值生效)

public static int test() {
    int a = 10;
    try {
        return a; // 先记录返回值10,待finally执行后返回
    } finally {
        a = 20; // 修改局部变量a
        System.out.println("finally: " + a); // 输出20
    }
}
// 调用test()返回:10(关键:try的return已记录a的副本,finally修改a不影响返回值)

场景2:finally中显式return(覆盖try的返回值)

public static int test2() {
    try {
        return 10;
    } finally {
        return 20; // finally的return会覆盖try的return
    }
}
// 调用test2()返回:20

场景3:引用类型(修改对象内容生效,修改引用不生效)

static class User { int age; }
public static User test3() {
    User u = new User();
    try {
        u.age = 10;
        return u; // 记录u的引用,指向堆中对象
    } finally {
        u.age = 20; // 修改对象内容,返回值的age为20
        // u = new User(); // 修改引用,不影响返回值(仍指向原对象)
    }
}
// 调用test3().age返回:20

核心总结

  • 基本类型:try的return会拷贝值的副本,finally修改原变量不影响返回值;
  • finally显式return:直接覆盖所有返回值;
  • 引用类型:修改对象内容生效,修改引用本身不生效。

4. TreeSet添加自定义对象时,compareTo与hashCode需如何配合?

思路

明确TreeSet的底层(TreeMap,依赖Comparable/compareTo),说明hashCode的非必要性,解释两者的配合原则。

回答示例

TreeSet底层基于TreeMap实现,核心依赖Comparable接口的compareTo方法(或Comparator比较器),hashCode方法对TreeSet的元素唯一性无影响,但需遵循“compareTo返回0则equals为true”的约定。

配合规则:

  1. compareTo是核心

TreeSet通过compareTo判断元素是否重复:若两个对象compareTo返回0,则视为同一元素,添加失败;

  1. hashCode的配合要求

虽TreeSet不依赖hashCode,但为了符合Java对象的通用约定(equals相等则hashCode相等),需保证:

示例

class User implements Comparable<User> {
    private int id;
    @Override
    public int compareTo(User o) { // 按id比较
        return Integer.compare(this.id, o.id);
    }
    @Override
    public boolean equals(Object o) { // 与compareTo一致,按id判断相等
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return id == user.id;
    }
    @Override
    public int hashCode() { // 与equals一致,基于id生成
        return Objects.hash(id);
    }
}

5. HashMap负载因子0.75是理论最优解还是工程折中?依据是什么?

思路

明确“工程折中”,从“时间/空间平衡”“泊松分布”两个维度解释依据。

回答示例

HashMap的负载因子0.75是工程折中方案,而非纯理论最优解,核心依据:

  1. 时间与空间的平衡
  2. 泊松分布的统计依据

哈希冲突的链表长度遵循泊松分布,负载因子0.75时,链表长度超过8的概率仅为0.00000006(十亿分之六),冲突概率极低,无需为更低的冲突概率牺牲大量内存。

6. ReentrantLock的公平锁与非公平锁在队列调度上有何区别?

思路

从“抢锁逻辑”“队列优先级”“性能”三个维度对比,突出公平锁的“先到先得”和非公平锁的“插队”特性。

回答示例

ReentrantLock的公平锁与非公平锁核心差异在锁竞争的队列调度逻辑

维度

公平锁

非公平锁

抢锁逻辑

先检查等待队列,队列非空则排队

先尝试CAS抢锁,抢不到再排队

队列优先级

严格FIFO,队列头节点优先获取锁

新线程可能“插队”(抢在队列头前)

性能

吞吐量低(频繁上下文切换)

吞吐量高(减少排队开销)

适用场景

要求严格顺序(如金融交易)

追求高并发(如普通业务系统)

核心细节:

  • 公平锁:线程获取锁时,必须先判断AQS等待队列是否有前驱节点,有则排队,无则抢锁,保证“先到先得”;
  • 非公平锁:线程获取锁时,先CAS尝试修改AQS的state变量(抢锁),成功则直接获取,失败再进入队列排队;可能出现“新线程抢过队列头线程”的情况,但减少了队列唤醒的开销。

7. wait()必须在synchronized块内调用的根本原因?

思路

核心讲“线程状态一致性”“防止虚假唤醒”,解释wait()与锁的绑定关系。

回答示例

wait()必须在synchronized块内调用的根本原因是保证线程状态的一致性,防止虚假唤醒

  1. 锁与等待的绑定

wait()

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏

全部评论

相关推荐

03-09 17:42
已编辑
福州大学 Java
给准备投这家公司的友友提供一下面经作为参考八股顺序不太记得了。1.自我介绍2.项目介绍(这块答得很烂,感觉面试官不感兴趣,都没怎么追问细节)3.讲讲mysql&nbsp;b+树(提到b+树基本结构,减少磁盘OI)4.事务的隔离级别(四个都提到了)5.讲讲JVM内存模型,双亲委派机制(基本都回答上来了)追问类加载器能不更改掉双亲委派&nbsp;(这个回答了无法轻易更改,因为安全问题)6.线程池的类型(这个忘记了)线程池核心参数(这个答上了)7.syn和reen的区别(这个当时只记得后者可以实现公平锁,现在才意识到还有很多不同)8.谈谈spring的IOC&nbsp;&nbsp;&nbsp;&nbsp;(讲了一下控制反转,解耦)9.讲一下如何处理循环依赖(提到了三级缓存,和只能解决单例下的循环依赖)10.容器了解吗(不太了解,只了解了一些docker但没真的部署过)11.大模型开发软件cursor和trae有使用过吗(没使用过)补充一点:追问了项目中事务是怎么实现的(这个确实不了解,只会用@Transactional)面试官建议:了解一些前端的知识,在校要主动多使用大模型开发,了解前沿技术。提到我代码能力还是基础不是很充足。一共面了20分钟,面完就知道大概率无了,感觉还是项目都没有怎么细问,个人感觉像是因为没有上线过的原因。有点疑问想咨询一下:这是我第一次面试,感觉面试官都是让我主动谈谈项目啊,八股啊。我感觉我如果一下把点都回答了,那面试官问的就都是我没准备的,但如果刻意讲讲的时候没有答完整,留一些让面试追问的又可能不会追问而是跳过,再觉得你基础不行。所以我很纠结这种讲讲谈谈要怎么回答合适,怎么把握那个度。也可能是我太菜了,前面项目那回答太差就挂了,后面只是走流程,所以才会这样。平常自己找AI面试都是AI会追问细节和具体内容,今天实际面一下发现差别还是好多。
查看14道真题和解析
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
昨天 10:38
实力求职者:真的绷不住了,第一张霸总人设,第二张求生欲拉满
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务