@SafeVarargs限制作用范围是因为可变参数底层编译为泛型擦除后的数组,若方法可被子类重写,子类可能不安全操作数组导致堆污染;故仅允许用于static、final或private方法以确保类型安全承诺不可被绕过。
因为可变参数(varargs)在底层被编译为数组,而泛型擦除后无法在运行时验证数组元素的真实类型。当方法可被子类重写时,子类可能破坏原始设计意图,导致堆污染(heap pollution)——即泛型集合中混入错误类型的对象,最终引发 ClassCastException。
如果允许非 final 实例方法使用 @SafeVarargs,子类就可能覆写该方法,并在内部以不安全方式操作 varargs 数组(比如将其暴露给外部、转型后存入其他泛型容器等)。而 final、static 或 private 方法无法被继承或重写,能确保注解所承诺的“类型安全操作”不会被意外打破。
从 Java 8 开始,@SafeVarargs 也允许用于 private 实例方法。这是因为 private 方法天然不具备可覆写性,且仅在当前类内调用,开发者能完全掌控其内部逻辑,风险可控。但即便如此,它仍不能用于普通 public/protected 非 final 方法——编译器会直接报错。
@SafeVarargs 不是魔法开关,而是开发者向编译器做的责任声明:我已确认这个方法对 varargs 的处理不会引发类型泄漏。JVM 和编译器只愿为那些“无法被外部干预”的方法背书。一旦方法可被重写,这份信任就失效了。
立即学习“Java免费学习笔记(深入)”;