我想用泛型和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
}
}
Run Code Online (Sandbox Code Playgroud)
这里的目的是断言传递给该函数的所有参数都是Class对象,扩展了作为第一个参数给出的Class.因此,main方法的两个第一行将编译,第三行将生成错误.
我的问题是:为什么我得到"类型安全:为varargs参数创建类的通用数组"消息前两行?
我在这里错过了什么吗?
附加问题:如何重新设计它以防止在每行调用"doNastyThingsToClasses"函数时显示此警告?我可以将其更改为"doNastyThingsToClasses(Class <A> parent,Class <?> ... classes)"并删除警告,但这也会删除编译时类型检查 - 如果我想要的话,那就太好了确保正确使用此功能.更好的解决方案?
我们使用了一些varargs函数,当我们转向java 1.7时,我们得到了一个奇怪的未经检查的警告.
功能在接口ICache中添加
public interface ICache<O> {
void add(Object source, O... objects);
}
Run Code Online (Sandbox Code Playgroud)
在界面中报告错误.
ICache.java:18: warning: [unchecked] Possible heap pollution from parameterized vararg type O
void add(Object source, O... objects);
where O is a type-variable:
O extends Object declared in interface ICache
1 warning
Run Code Online (Sandbox Code Playgroud)
O扩展了Object,作为其通用缓存类.
我阅读了xlint警告并且我们在未经检查的情况下编译,但是http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#xlintwarnings似乎暗示这个错误应该是[varargs]类型不是未经检查的类型.
我错过了什么吗?
我已经声明了以下方法:
private void mockInvokeDBHandler(Map<String, Object>... rows) {
List<Map<String, Object>> allRows = Arrays.asList(rows));
// rest of method omitted
}
Run Code Online (Sandbox Code Playgroud)
客户端使用类似的东西调用它
Map<String, Object> row1 = new HashMap<String, Object>();
Map<String, Object> row2 = new HashMap<String, Object>();
mockInvokeDBHandler(row1, row2);
Run Code Online (Sandbox Code Playgroud)
但是,上面显示的最后一行会生成警告
类型安全:为varargs参数创建一个通用的Map数组
我不完全理解这一点,但我想这是因为varargs params被转换为数组,并且拥有一个类型为泛型类的数组是个坏主意(因为泛型是不变的,而数组则不是).
我可以通过将方法重新定义为解决此问题
private void mockInvokeDBHandler(List<Map<String, Object>> rows) {
}
Run Code Online (Sandbox Code Playgroud)
但这会将行对象放入客户端的List中,这是我宁愿避免的.有更好的解决方案吗?