理想汽车 java后端实习

本文最后更新于:2025年10月21日 晚上

理想汽车 java后端实习

面试信息:

  • 时间:2025-10-21
  • 形式:线上
  • 时长:35min

自我介绍

时隔3个月的首场面试,十分紧张(面试官让我别紧张),一直在说这个💦。自我介绍的叙述准备还可以,需要多加练习,更流畅。时间控制在2分钟,节奏不错。

实习拷打

讲一讲你在实习中详细参与的的模块,讲一讲设计和难点

  • 相似工单分析:设计提示词结构化提取工单信息,计算向量,相似度分析,辅助群诉分析
  • 领导审批功能:需求介绍 -> 写入数据库 -> 通知信息

分布式锁的业务场景?如何实现的?

主要业务场景是防止由于重复点击或网络重试导致的同一审批操作被多次执行、重复落库,用分布式锁保证在并发下审批只执行一次。

实现:

我们做成了一个通用注解 @HotlineLock(args={"#dto.handleId"}),底层用 AOP 切面在方法执行前后自动加锁和解锁。

加锁时,动态解析方法的入参,拼出唯一key,大致的格式是类名+方法名+业务ID,然后用SETNX命令加锁,同时设置过期时间、重试次数和重试间隔。如果一段时间内没拿到锁,就直接返回“系统繁忙”。

方法执行完以后,无论成功还是异常,都会在 finally 里自动释放锁,保证不会出现锁被遗留的问题。同时因为方法本身带事务,业务出错会自动回滚,但锁一定会被释放。

你锁上去了以后,但是后续再进行审批的时候报错了怎么办?

  • 业务本身有@Transactional注解,失败数据会回滚,不会留下脏数据
  • 切面里用 try…finally,无论成功/失败都会释放锁,避免把审批单一直锁住;
  • 即使线程崩掉,仍然有redis的过期时间做兜底,不会一直锁住
  • 数据库id本身业务幂等

如何确定锁住的是哪一个审批单

我们把分布式锁做成了方法级的通用注解,但锁的粒度是业务对象级。做法是:在注解里声明从入参取哪个业务ID(比如‘从入参里的 handleId’),切面在运行时解析这个ID,将方法类名,方法名,ID拼成唯一的锁Key,所以同一套锁可以给不同方法、不同字段名的业务通用使用。

八股

==equal的区别?

==直接比较引用地址。equal默认也是比较地址,通常重写用来比较内容。一般重写equal也需要重写hashCode(),保证相同对象在哈希结构中保持一致。

表中有字段 a、b、c、d,建立了联合索引 (a, b, c)。三条 SQL:where a = ? and b = ?,where a = ? and c = ?,where b = ? and c = ? 问:哪几条可以用到索引?

mySQL遵循最左前缀原则。

  • 第一条可以完全命中查询
  • 第二条 a,c 只会用到 a 部分,因为中间的 b 被跳过;
  • 第三条 b,c 不满足最左前缀,索引失效。

有联合索引 (a, b, c)。两条 SQL:SELECT a, c FROM t WHERE a=? AND b=?; SELECT a, d FROM t WHERE a=? AND b=?; 问:两条语句执行性能是否相同?为什么?

这两条 SQL 性能不同
第一条(返回 a,c)能用覆盖索引(covering index)
第二条(返回 a,d)需要回表(回到主键表取 d),所以性能更低。

java值传递

1
2
3
4
5
6
7
8
9
10
11
12
13
void a() {
List<Integer> list = new ArrayList<>();
list.add(1);
b(list);
// 问:这里 list 里有什么?
}

void b(List<Integer> list) {
list.add(2);
list = new ArrayList<>(); // “new 一下”
list.add(3);
}

最终的list是[1,2]

  • Java 是值传递,传对象时传的是对象引用的副本。
  • a() 里创建的 list 传到 b() 后,b() 对它 add(2) 会影响外层,因为两者引用同一个对象;
  • b() 里重新 new 了一个 List 后,只改了自己那份引用,外层没受影响。

一个线程修改变量后,其他线程能马上看到最新值,通常用什么关键字?

volatile保证变量的可见性(visibility),即一个线程修改了变量的值,其他线程能立即看到最新值。

手撕

实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton {
private static Singleton instance;

private Singleton() {}

public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton(); // 延迟创建
}
return instance;
}
}

反问

主要业务是什么