我已声明以下方法:
private void mockInvokeDBHandler(Map<String, Object>... rows) {
List<Map<String, Object>> allRows = Arrays.asList(rows));
// rest of method omitted
}
客户使用
之类的东西调用它Map<String, Object> row1 = new HashMap<String, Object>();
Map<String, Object> row2 = new HashMap<String, Object>();
mockInvokeDBHandler(row1, row2);
但是,上面显示的最后一行会生成警告
类型安全:为varargs参数
创建一个通用的Map数组
我不完全理解这一点,但我想这是因为varargs params被转换为数组,并且拥有一个类型为泛型类的数组是个坏主意(因为泛型是不变的,而数组则不是)
我可以通过将方法重新定义为
来解决此问题private void mockInvokeDBHandler(List<Map<String, Object>> rows) {
}
但这会将行对象放入客户端的List中,这是我宁愿避免的。有更好的解决方案吗?
答案 0 :(得分:12)
要将参数传递给varargs方法,编译器会将参数放入数组中。
警告是让你知道编译器不能保证数组中的每个元素 - varags方法的每个参数 - 都是真正的Map<String, Object>
。
这是一个令人讨厌的警告,因为除了重新定义方法签名以不使用varargs之外,你无法解决这个问题。 IMO可以安全地忽略,只要您非常确定这些参数的实际运行时类型(在这种情况下,您就是这样)。
答案 1 :(得分:4)
除了将@SuppresWarning("unchecked")
添加到方法:)
既然你说它是私有方法,在这种情况下就没有“客户”而且你控制了这个方法,所以忽略这个警告似乎是合理的。
有几次我创建了将参数化类型作为varargs参数的方法时,我创建了一些重载:
void mockInvokeDBHandler(Map<String, Object> map1)
void mockInvokeDBHandler(Map<String, Object> map1, Map<String, Object> map2)
void mockInvokeDBHandler(Map<String, Object> map1, Map<String, Object> map2, Map<String, Object>... othermaps)
这可以避免一些警告,具体取决于提供的参数数量。
答案 2 :(得分:3)
对于任何登陆这里的人来说,答案有点老了。 Java 7引入了@Safevarargs
注释来解决这个问题:
@SafeVarargs
private void mockInvokeDBHandler(Map<String, Object>... rows) {
来自javadoc:
程序员断言注释方法的主体或 构造函数不会对其执行潜在的不安全操作 varargs参数。将此批注应用于方法或 构造函数抑制关于a的未经检查的警告 不可恢复的变量arity(vararg)类型并且抑制 有关调用时参数化数组创建的未经检查的警告 位点。
答案 3 :(得分:2)
通过使用一些构建器界面(例如the one I'm using),您可以降低使用List而不是varargs的负担。使用这个CollectionBuilder,它会变成这样:
mockInvokeDBHandler(CollectionBuilder.<Map<String, Object>>list().add(map1).add(map2).get());
虽然没有通用的args但它更漂亮:
import static at.molindo.utils.collections.CollectionBuilder.list
List<String> list = list(String.class).add("foo").addAll(set).get();
它确实比varargs解决方案更长,但无论如何都有时非常方便。