代码之家  ›  专栏  ›  技术社区  ›  Dónal

一般varargs的警告

  •  7
  • Dónal  · 技术社区  · 14 年前

    我声明了以下方法:

    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参数创建映射的泛型数组

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

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

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

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

    4 回复  |  直到 7 年前
        1
  •  12
  •   matt b    14 年前

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

    警告是让您知道编译器不能保证数组中的每个元素(varags方法的每个参数)都是真正的 Map<String, Object> .

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

        2
  •  4
  •   Uhlen    14 年前

    除了添加 @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)
    

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

        3
  •  3
  •   Brendan Humphreys    7 年前

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

    @SafeVarargs
    private void mockInvokeDBHandler(Map<String, Object>... rows) {
    

    从javadoc:

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

        4
  •  2
  •   sfussenegger    14 年前

    通过使用一些构建器接口(例如 the one I'm using ). 使用这个CollectionBuilder,它会变成这样:

    mockInvokeDBHandler(CollectionBuilder.<Map<String, Object>>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();
    

    作为varargs解决方案,它当然要长一些,但有时还是很方便的。