通用varargs的警告

时间:2010-11-23 15:45:33

标签: java generics variadic-functions

我已声明以下方法:

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中,这是我宁愿避免的。有更好的解决方案吗?

4 个答案:

答案 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解决方案更长,但无论如何都有时非常方便。