Java generics and varargs

2022-09-01 06:39:50

我想实现一个同时具有泛型和varargs的函数。

public class Question {
    public static <A> void doNastyThingsToClasses(Class<A> parent, Class<? extends A>... classes) {
        /*** something here ***/
    }
    public static class NotQuestion {
    }
    public static class SomeQuestion extends Question {
    }
    public static void main(String[] args) {
        doNastyThingsToClasses(Object.class, Question.class, SomeQuestion.class); // OK
        doNastyThingsToClasses(Question.class, SomeQuestion.class); // OK
        doNastyThingsToClasses(Question.class, Object.class, SomeQuestion.class); // compilation failure
    }
}

此处的目的是断言传递给此函数的所有参数都是扩展作为第一个参数给出的 Class 的 Class 对象。因此,main 方法的前两行将编译,第 3 行将生成错误。

我的问题是:为什么我在前两行收到“类型安全:为varargs参数创建了类的泛型数组”消息?

我在这里错过了什么吗?

附加问题:如何重新设计它以防止此警告显示在调用“doNastyThingsToClasses”函数的每一行上?我可以把它改成“doNastyThingsToClasses(Class<A> parent, Class<?>...classes)“并摆脱警告,但这也消除了编译时类型检查---,如果我想确保正确使用这个函数,那就不太好了。有没有更好的解决方案?


答案 1

与往常一样,Angelika Langer的Java泛型FAQ非常详细地解释了它。(滚动到“为什么编译器有时会在调用”varargs“方法时发出未经检查的警告?” - ID不能正常工作。

基本上,您最终会以比平常更糟糕的方式丢失信息。Java泛型中的另一个小痛点:(


答案 2

Jon Skeet的答案(当然)是正确的。我将通过指出你可以摆脱这个警告来稍微扩展一下,用一个大的“如果”。如果您愿意承诺使用 Java 7 构建项目,则可以避免此警告。

Bob Lee写了一个提案,作为Project Coin的一部分,在方法声明站点而不是使用站点禁止此警告。

这个建议在JDK7中被接受(尽管语法略有变化,改为);如果您感到好奇,可以查看向 JDK 添加此支持的提交@SuppressWarnings("varargs")

不一定对你有帮助,但我想我会把这个问题作为一个单独的答案,这样它就可以为未来的读者服务,他们可能很幸运地生活在一个后Java-7的世界里。