我想用泛型和可变参数实现一个函数。
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
}
}
此处的目的是断言传递给此函数的所有参数都是扩展作为第一个参数给定的类的类对象。所以 main 方法的前两行会编译,第三行会产生错误。
我的问题是: 为什么我在前两行收到“类型安全:为可变参数参数创建类的通用数组”消息?
我在这里遗漏了什么吗?
Jon Skeet 的回答(当然)是正确的;我将通过指出您可以通过一个大的“如果”来摆脱这个警告来稍微扩展它。如果您愿意承诺使用 Java 7 构建项目,则可以避免此警告。
Bob Lee 写了 a proposal 让这个警告在方法声明站点被抑制,而不是使用站点,作为 Project Coin 的一部分。
JDK7 接受了这个提议(尽管语法略有变化,为
@SuppressWarnings("varargs")
);你可以,如果你很好奇,看看将此支持添加到 JDK 的提交。
不一定对你有帮助,但我想我会把它作为一个单独的答案,以便它继续存在于未来的读者中,他们可能有幸生活在后 Java-7 世界中。
作为旁注,可以使用 Java 7 中引入的 @SafeVarargs 注释来抑制警告。
@SafeVarargs
public static <A> void func( Class<A> parent, Class<? extends A>... classes ) {
// Do func...
}
我解决这个问题的方法是
class Nastier {
private final Class<A> parent;
public Nastier(Class<A> parent) {
this.parent = parent;
}
public <A, C extends A> Nastier do(Class<? extends A> clazz) {
System.out.println(clazz);
return this;
}
}
public static void main(String[] args) {
Nastier nastier = new Nastier(Object.class);
nastier.do(Question.class).do(SomeQuestion.class).do(NotQuestion.class);
}
public class Question {
public static <A, C extends A> void doNastyThingsToClasses(Class<A> parent, List<Class<? extends A>> classes) {
/******/
for(Class<? extends A> clazz : classes) {
System.out.println(clazz);
}
}
public static class NotQuestion {
}
public static class SomeQuestion extends Question {
}
public static void main(String[] args) {
ArrayList<Class<? extends Object>> classes = new ArrayList<Class<? extends Object>>();
classes.add(Question.class);
classes.add(SomeQuestion.class);
classes.add(NotQuestion.class);
doNastyThingsToClasses(Object.class, classes);
ArrayList<Class<? extends Question>> clazzes = new ArrayList<Class<? extends Question>>();
clazzes.add(Question.class);
clazzes.add(SomeQuestion.class);
clazzes.add(NotQuestion.class); // yes, this will _not_ compile
doNastyThingsToClasses(Question.class, clazzes);
}
}
唯一的缺陷是用于填充用于携带函数参数的集合的长代码。
Class<? extends A>
... 必须扩展第一个参数所在的类(例如,第一个参数是
Question
所以第二个参数是扩展
Question
.的东西 细分:
NastyThingsToClasses(Object.class, Question.class, SomeQuestion.class); // OK
Object
所以第二个参数是正确的。
NastyThingsToClasses(Question.class, SomeQuestion.class); // OK
SomeQuestion
扩展
Question
所以这是公平的游戏。
NastyThingsToClasses(Question.class, Object.class, SomeQuestion.class);
Object
不扩展
Question
因此错误。
希望这能解决问题。