【问题标题】:Is this use of varargs safe?使用可变参数安全吗?
【发布时间】:2014-10-24 09:59:36
【问题描述】:

我有一种 util 方法可以将一个类型的 varargs 转换为该类型的数组 - 它看起来像这样:

public K[] array(K... ks) {
    return ks;
}

用例是这样的,当调用需要数组的方法时,您可以简单地执行 array(val1, val2, val3),而不是定义数组。

但是,IntelliJ 给了我堆污染警告。我在一定程度上理解这意味着什么,但我对具体细节没有太多经验 - 所以,我想知道我是否可以添加 @SafeVarargs 以及这种方法是否真的安全。

IntelliJ 说:

  问题概要     参数化可能造成的堆污染 第 249 行的可变参数类型

问题解决    最终确定并注释为@SafeVarargs

K 与 V 一起被声明为类的类型参数。

【问题讨论】:

  • IMO 你不需要这种方法,用Whatever[] whateverArray = { val1, val2, val3, ...};
  • 你能给出堆污染警告的exact细节吗?类型参数K声明在哪里?
  • @Luiggi,是的,但它是一个实用程序。 K[] keys = { key1, key2, key3 }; object.method(keys); vs object.method(array(key1, key2, key3)); - 第二个更容易编写,尤其是当你经常这样做时。
  • 不,不是。如果您需要即时创建这样的数组,请这样做:foo.method(new Whatever[] { val1, val2, val3, ... });。不需要您的 utility 方法。
  • @LuiggiMendoza:写foo(array(a, b, c)) 比写foo(new Whatever[]{a, b, c})明显冗长/视觉上分散注意力。

标签: java


【解决方案1】:

不,这不安全 - 如果从另一个使用泛型的方法调用。这是一个完整的示例,看起来没问题,但会引发异常:

class Utility<K> {   
    public K[] array(K... ks) {
        return ks;
    }

    public K[] otherMethod(K k1, K k2) {
        return array(k1, k2);
    }
}    

class Test {
    public static void main(String[] args) throws Exception {
        Utility<String> util = new Utility<String>();
        // Bang!
        String[] array = util.otherMethod("foo", "bar");
    }
}

当编译器为otherMethod 创建字节码时,它不能创建一个正确类型的数组来传递给array,因为它不知道@987654324 的类型@。由于类型擦除,它只创建一个带有值的Object[]。所以在main 中,有一个从otherMethodString[] 的结果的隐藏转换...并且在执行时失败。

如果您直接从真正知道参数类型的代码中调用array,那很好,因为隐式创建的数组将是正确的类型。

【讨论】:

  • 谢谢。只要这是唯一(在合理范围内)可能导致问题的情况,我正在做的事情应该没问题。
  • 这里要小心谨慎,@DziNeIT。如果这只是一个愚蠢的行为,并且您是唯一使用此代码的人,那么请继续。但是,我知道如果遇到这样的事情我会怎么想。不过,这是一个很好的问题,也有同样好的答案。 :)
【解决方案2】:

您可以只告诉您的方法如何转换为适当的数组。我发现的一种方法是将数组传递给带有变量的方法,然后复制到它。

public K[] otherMethod(K[] parent, K k1, K k2) {
    List<K> list = new ArrayList<K>();
    Collections.addAll(list, array(k1, k2));
    list.toArray(parent);
    return parent;
}

现在输出取决于 Collections.toArray() 方法,如果数组中没有足够的空间,则返回 null,或者如果有多余的空间,未使用的值将为 null。

class Test {
    public static void main(String[] args) throws Exception {
        Utility<String> util = new Utility<String>();
        String[] array = util.array("one", "two", "three");
        array = util.otherMethod(array, "x", "y");
        printArr(array); // prints: x    y    null

        Utility<Integer> util2 = new Utility<Integer>();
        Integer[] intarray = util2.otherMethod(new Integer[1], 1, 2);
        printArr(intarray); // prints: null
        Integer[] intarray = util2.otherMethod(new Integer[2], 1, 2);
        printArr(intarray); // prints: 1    2
    }

    static void printArr(Object[] objArr) {
        for (Object o:objArr) System.out.print(o+"\t");
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 1970-01-01
    • 2022-09-25
    • 2018-03-20
    相关资源
    最近更新 更多