面灵AI→

恒生电子一面面经(Java 开发)

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 简短自我介绍。
  2. 介绍一下 final 关键字。
  3. 讲一下反射。
  4. 哪些框架用了反射?
  5. 讲一下多线程。
  6. 你用过哪些中间件?
  7. 怎样实现分布式锁?
  8. 什么时候会用到分布式锁?
  9. Spring 你掌握得怎么样?
  10. AOP 的实现方式有哪些?
  11. 讲一下 HTTPS。
  12. HTTPS 的加密传输过程是怎样的?
  13. 数据库你熟悉哪一种?
  14. SQL 慢查询怎么处理?
  15. 有接触过 AI 编程吗?
  16. 工作地点确认。
  17. 期望薪资是多少?
  18. 手头有没有别的 offer?
  19. 反问。

《参考解析》

final 关键字。它有三处语义:修饰变量表示只能赋值一次(成员变量必须在声明处或构造器中初始化,引用不可变不代表对象内容不可变,比如 final List 仍能 add);修饰方法表示不能被子类重写;修饰类表示不能被继承(如 String、Integer 这些不可变类)。有两个容易被追问的点:一是 final 与 JMM 的关系——正确构造的对象的 final 字段有「安全发布」保证,其他线程能看到构造完成后的值,不需要额外同步;二是 static final 常量在编译期折叠进调用方字节码,改了常量值需要重新编译引用方,这是线上「改了配置没生效」的经典坑。

反射与框架。反射是在运行期获取类信息并操作对象的能力:Class.forName 或 类.class 拿到 Class 对象,通过 getDeclaredFields/Methods/Constructors 获取成员,用 setAccessible(true) 突破私有访问,再 newInstance 与 invoke 发起调用。它的代价是绕过编译期检查(错误推迟到运行期)、性能比直接调用差(现代 JVM 在调用点稳定后会有膨胀与内联优化,差距已经不大,主要成本在查找与装箱)、以及破坏封装。几乎所有主流框架都靠它:Spring 的依赖注入与注解扫描、MyBatis 的结果集映射、Jackson 的序列化、JUnit 的用例发现、以及各类 ORM 与 AOP 代理。

AOP 的实现方式。AOP 把日志、事务、权限、埋点这类横切关注点从业务代码里抽出来,核心概念是切面、切点、通知与织入时机。实现方式有两类:静态织入(AspectJ 的编译期或类加载期织入,性能最好但需要额外编译器或 agent)和动态代理(Spring AOP 默认走这条)。动态代理又分两种:接口代理用 JDK 的 Proxy 加 InvocationHandler,通过实现同一接口生成代理类,因此要求目标类至少实现一个接口;类代理用 CGLIB 生成目标类的子类并覆写方法,因此不能代理 final 类与 final 方法,私有方法与同类内部调用也不会走代理——这是「@Transactional 或 @Cacheable 加了却不生效」的第一大原因,解法是从容器里拿代理对象调用自己(AopContext.currentProxy())或把方法拆到另一个 Bean。另外 Spring Boot 2.x 之后默认用 CGLIB(proxyTargetClass=true),「代理边界即事务边界」这句话能把事务失效的场景串起来。

分布式锁的实现与使用场景。单机锁(synchronized、ReentrantLock)只在同一 JVM 内有效,一旦服务多实例部署,需要用外部存储做互斥。主流有三种:Redis、ZooKeeper、数据库。Redis 的标准做法是 SET key value NX PX ttl,value 用 UUID 加线程标识,释放时用 Lua 脚本先比对 value 再删除(保证原子性,防止误删别人的锁);必须有过期时间防止持有者宕机造成死锁;业务可能超时就要续期(Redisson 的看门狗默认每 10 秒续到 30 秒,只在未显式指定 leaseTime 时启用)。ZooKeeper 用临时顺序节点加 Watch,天然有会话失效释放与公平排队,一致性更强但性能低于 Redis、且需要额外运维。数据库可以用唯一索引插入或 SELECT ... FOR UPDATE,实现简单但并发差,适合低频任务互斥。使用场景的共同特征是「跨进程需要互斥的临界区」:定时任务多实例只让一个跑、秒杀或抢券的库存扣减、防止同一订单被重复处理、幂等控制、以及跨服务的资源占用。要强调的边界是:分布式锁只能降低并发冲突,不能替代幂等——主从切换、网络分区、GC 停顿都可能让锁失效,所以业务侧仍要有唯一约束与状态机兜底;锁的粒度要尽量小、等待要用带超时的 tryLock 避免线程堆积,Redlock 在强一致要求下的争议也要能说出一二。

HTTPS 的加密传输过程。HTTPS 就是 HTTP 加 TLS,目标是在不安全的信道上同时实现机密性、完整性与身份认证。握手(以 TLS 1.2 的常见流程为例)大致是:客户端发 ClientHello(支持的版本、密码套件、随机数 A);服务端回 ServerHello(选定套件、随机数 B)与证书链;客户端校验证书(有效期、域名、签发链,验证书是否被吊销),校验证书公钥确实能解开服务端用私钥做的签名,从而确认服务端身份;客户端生成预主密钥,用服务器证书里的公钥加密后发过去(RSA 密钥交换;现代用 ECDHE 则双方各自算共享密钥,具备前向安全性),双方用三个随机数派生出会话密钥;之后交换 Finished(对前面所有握手消息的摘要做校验)确认握手未被篡改,再切换为对称加密传输应用数据。TLS 1.3 把握手压到一次往返(1-RTT)并砍掉了 RSA 密钥交换、只保留前向安全的方案。要理解「为什么用非对称加密协商、用对称加密传输」:非对称算法慢且只能加密小块数据,适合做密钥交换与签名;对称算法(AES-GCM)快,适合加密业务数据,同时 GCM 这类 AEAD 模式顺带提供完整性校验。证书体系的根在操作系统与浏览器的受信任根 CA 列表,中间证书用于减少根证书暴露风险。

SQL 慢查询与数据库选型。治理慢查询先定位再优化:开启慢查询日志(slow_query_log 加 long_query_time,线上可先用 pt-query-digest 聚合),用 EXPLAIN 看执行计划,重点看 type(出现 ALL 是全表扫描)、key(实际用了哪个索引)、rows(预估扫描行数)、Extra(Using filesort、Using temporary 是常见瓶颈信号)。优化手段按性价比排序:建合适的联合索引并遵守最左前缀、避免索引失效(对列做函数运算、隐式类型转换、前导模糊 like '%x'、or 混用非索引列、!= 与 is null 视情况)、用覆盖索引减少回表、只查需要的列而不是 select *、大分页改用游标或延迟关联(where id > last_id limit n)、拆分大事务与批量写、必要时做归档与分表,以及从业务上减少查询次数(缓存、异步化)。数据库选型方面,OLTP 业务默认 InnoDB(事务、行锁、MVCC、崩溃恢复),需要离线分析或海量写入才考虑列存或 ClickHouse 这类专用引擎;被问「熟悉哪种」时,把 InnoDB 的索引结构(B+ 树聚簇索引、二级索引回表)、事务与锁、以及上面这套慢查询方法论讲清就够了。

面试节奏。原帖记录面试 15 分钟结束、问题常规,这类「短平快」的一面关键是把每个问题答成「结论加一层原理加一个例子」的三段式,不要展开成讲座;同时把工作地点、期望薪资、手头 offer 这类问题准备成确定性回答(给区间、说明依据、表达意向),它们是这一轮真正的筛选项。被问 AI 编程时,如实说清用在哪些环节(写样板代码、生成测试、读陌生代码),并强调验证手段(跑测试、读 diff、类型检查),比声称「全靠 AI」更可信。