升级一个公共 SDK 后,原来正常的方法调用突然走了另一个重载,你会怎么解释和排查?
我的判断
重载在编译期按静态类型选方法,重写才在运行期按实际对象分派;SDK 新增重载后,重新编译可能改变原来的绑定结果。
我会先确认这次升级有没有重新编译调用方。已经编译好的字节码里保存的是目标方法描述符,不会因为 jar 多了一个重载就自动改道;但源码重新编译后,编译器会重新选择“最具体”的重载,null、自动装箱和可变参数最容易让结果变化。
例如原来只有 send(Object),SDK 新增 send(String) 后,send(null) 重新编译就会绑定到 String 版本。若新增两个互不包含的引用类型,甚至会直接编译歧义。
排查时我会对比升级前后的 API 签名和调用点静态类型,再用 javap -c 看字节码里的 invokevirtual 目标,而不是只盯运行时对象。修复通常是让调用意图显式:避免裸 null,必要时强转,或者改成不同方法名。
公共 SDK 不应随意增加容易与装箱、可变参数冲突的重载。源码兼容不等于重新编译后的行为兼容。