第 4 章 API 变更分析:新增、修改、废弃、删除

SDK 版本升级,说白了就是看它的 API 变了什么。

我刚接触兼容性测试时,拿到新版 SDK 就一股脑跑用例。后来发现,很多坑都是 API 悄悄改出来的。所以我现在的习惯是——先做个 API 变更分析,把四种变化摸清楚再去动测试用例。

这一章,咱们就聊聊怎么分析 API 的四种变更:新增、修改、废弃、删除。

API 变更分类框架 API 变更 新增 修改 废弃 删除 💡 关键思路: 新增类:不破坏现有功能,但可能带来依赖风险 修改/废弃/删除类:极有可能破坏现有功能,必须逐项回归 按对现有功能的破坏风险排序:删除 > 修改 > 废弃 > 新增 实际工作中,这四种变更往往混合出现,需要逐条分析

4.1 新增 API

新加了个方法、新加了个类、新加了个常量。看起来人畜无害,对吧?

事实上,新增 API 通常不会破坏现有功能。但它可能带来两个隐患:

  • 符号冲突:你项目里自己定义的同名函数,跟新 API 撞上了。
  • 依赖冲突:新 API 内部引用了另一个第三方库,导致你的项目里同样的库版本不一致。
我的一点经验: 新增 API 反而最容易被忽略。大家觉得没事,结果编译阶段静悄悄通过了,运行时却因为类加载顺序出错。所以我的做法是——即使只是新增,也要跑一遍主流程冒烟测试。

4.2 修改 API

这个最头疼。改了参数类型、改了返回值、改了方法签名,甚至改了内部行为逻辑。

举个例子:原来 getUser(int id) 改成 getUser(String id)。编译直接报错,倒还好。就怕那种签名不变、行为变了的哑修改。

// 旧版本:返回值可能为 null
public User findUser(String name);

// 新版本:保证不返回 null,找不到时抛异常
public User findUser(String name);

你看,编译没问题,但原来依赖 null 判断的代码全崩了。我就在项目里遇到过这种坑——线上日志突然出现一堆 NullPointerException,查了两天才发现是 SDK 悄悄改了内部约定。

⚠️ 特别注意: 修改 API 时,一定要对比文档变更日志和源码 diff。光看方法签名是不够的,要留意注释中的「行为变更」说明。

4.3 废弃 API

打上了 @Deprecated 注解,或者标记为 deprecated。意味着将来会删除。

废弃是个缓冲期。我习惯的做法是:

  1. 检查自己项目里有没有用到这些废弃 API。
  2. 有的话,立即替换成新推荐的替代 API。
  3. 替换后做全量回归——因为替代 API 的行为可能不完全一样。

你可能会问:“既然还能用,能不能先不改?”

嗯,我建议别拖。我以前在一个项目里拖了三个版本,结果某次升级直接把废弃 API 删了,编译失败,紧急加班改了一个通宵。所以,见到废弃就立改。

关键动作: 在测试报告中列出所有废弃 API 及其替代方案,作为待办项跟踪,直到全部替换完毕。

4.4 删除 API

删了就是真的没了。编译直接报错,这是最直观的破坏。

需要做的是:

  • 确认在你的项目中是否引用了该 API。
  • 如果有,查它的替代方案是什么。
  • 如果没有引用,也要小心——你的间接依赖(比如第三方库)是否引用了它。

举个例子:新版 SDK 删除了 Utils.encode(),你的项目没直接调它,但你的网络库 NetLib 调了。一升级,NetLib 加载失败,整个功能瘫痪。

⚠️ 避坑指南: 我曾经因为忽略间接依赖吃过亏。现在我每次升级前,都会用依赖分析工具(比如 jdeps 或 gradle dependencies)把全项目的 API 引用扫描一遍,再对照删减清单。

4.5 如何快速找出这些变更

手动一个一个翻 API 文档不现实。我常用的方法:

方法 适用场景 命令或工具
源码 diff 有 SDK 源码时 diff -r old_src/ new_src/
JAR 对比工具 只有二进制包时 javap -public -classpath new.jar + old.jar
API 变更检测专用工具 Java 生态 japicmp, clirr, revapi
官方发布说明 所有 SDK CHANGELOG.md / Release Notes

说说我的习惯:小版本升级,我直接用 japicmp 做二进制对比,几秒钟出一份变更报告。大版本升级,我会先读官方 Release Notes,再用 diff 扫一遍。

4.6 变更分析与兼容性决策矩阵

拿到变更清单后,怎么判断要不要做兼容性适配?我列了一张决策表:

变更类型 影响范围 推荐动作 测试优先级
新增 仅新增功能,不影响旧代码 可选,建议至少跑主流程 低
修改(签名不变) 运行时行为可能变化 必须逐项验证 高
修改(签名变化) 编译失败 必须适配代码 高
废弃 暂时不影响,但需替换 必须替换,替换后回归 中
删除 直接编译/运行失败 必须找到替代方案并适配 最高
一句话总结: API 变更分析不是一次性活,而是随着版本升级持续迭代的过程。每次升级前把四种变更过一遍,就能把绝大部分兼容性问题扼杀在测试之前。