Java 通用变参数警告

Java 通用变参数警告,java,generics,variadic-functions,Java,Generics,Variadic Functions,我声明了以下方法: private void mockInvokeDBHandler(Map<String, Object>... rows) { List<Map<String, Object>> allRows = Arrays.asList(rows)); // rest of method omitted } private void mockInvokeDBHandler(映射…行){ List allRows=Arrays.asL

我声明了以下方法:

private void mockInvokeDBHandler(Map<String, Object>... rows) {
    List<Map<String, Object>> allRows = Arrays.asList(rows));
    // rest of method omitted
}
private void mockInvokeDBHandler(映射…行){
List allRows=Arrays.asList(rows));
//方法的其余部分省略
}
它由客户机使用以下命令调用

Map<String, Object> row1 = new HashMap<String, Object>();
Map<String, Object> row2 = new HashMap<String, Object>();

mockInvokeDBHandler(row1, row2);
Map row1=newhashmap();
Map row2=新的HashMap();
mockInvokeDBHandler(第1行,第2行);
但是,上面显示的最后一行会生成警告

类型安全:为varargs参数创建一个通用的Map数组

我不完全理解这一点,但我猜这是因为varargs参数被转换为数组,而让数组的类型为泛型类是个坏主意(因为泛型是不变的,而数组不是)

我可以通过将该方法重新定义为

private void mockInvokeDBHandler(List<Map<String, Object>> rows) {
}
private void mockInvokeDBHandler(列出行){
}

但这会增加将行对象放入客户机列表的负担,我宁愿避免这样做。有更好的解决方案吗?

要将参数传递给varargs方法,编译器将把参数放入数组中

警告是让您知道编译器不能保证数组中的每个元素(varags方法的每个参数)都是真正的
映射


这是一个有点恼人的警告,因为除了将方法签名重新定义为不使用varargs之外,您无法解决这个问题。在我看来,只要您非常确定这些参数的实际运行时类型(在本例中,您就是这样),就可以安全地忽略这些参数。

除了向方法添加
@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)
void mockInvokeDBHandler(映射图1)
void mockInvokeDBHandler(映射1、映射2)
void mockInvokeDBHandler(映射1、映射2、映射…其他映射)

这可以避免一些警告,具体取决于提供的参数数量。

您可以通过使用一些构建器界面(例如,like)来降低使用列表而不是varargs的负担。使用此CollectionBuilder,它会变成这样:

mockInvokeDBHandler(CollectionBuilder.<Map<String, Object>>list().add(map1).add(map2).get());
mockInvokeDBHandler(CollectionBuilder.list().add(map1.add)(map2.get());
但是,如果没有通用参数,它会更漂亮:

import static at.molindo.utils.collections.CollectionBuilder.list

List<String> list = list(String.class).add("foo").addAll(set).get();
import static at.molindo.utils.collections.CollectionBuilder.list
List List=List(String.class).add(“foo”).addAll(set.get();

作为varargs解决方案,它当然要长一些,但无论如何,它有时非常方便。

对于任何登陆这里的人来说,答案都有点陈旧。Java 7引入了
@Safevarargs
注释来解决这个问题:

@SafeVarargs
private void mockInvokeDBHandler(Map<String, Object>... rows) {
@SafeVarargs
私有void mockedbhandler(映射…行){
从javadoc:

一种程序员断言,表示带注释的方法的主体或 构造函数不会在其上执行潜在的不安全操作 varargs参数。将此批注应用于方法或 构造函数将抑制有关 不可归变量arity(vararg)类型和抑制 关于调用时创建参数化数组的未选中警告 地点


我想你可以忽略这个警告。我确信你的实际代码已经编译好了,但是你在这里似乎有一个发布错误:
ListMap allRows
,应该是
List allRows
。@Mark E-谢谢,代码很好,只是在我的帖子中输入了一个错误。避免这种重载正是我想使用vararg和met的原因hod必须是有效的最终版本