Java 使用varargs安全吗?

Java 使用varargs安全吗?,java,Java,我有一种util方法,可以将某个类型的varargs转换为该类型的数组-如下所示: public K[] array(K... ks) { return ks; } 用例是这样的,当调用一个需要数组的方法时,您不需要定义数组,而只需执行数组(val1、val2、val3) 然而,IntelliJ给了我堆污染警告。我在某种程度上理解这意味着什么,但我对细节没有太多经验——因此,我想知道我是否可以添加@SafeVarargs,以及这个方法是否真正安全 IntelliJ说: 问题简介参数化堆

我有一种util方法,可以将某个类型的varargs转换为该类型的数组-如下所示:

public K[] array(K... ks) {
    return ks;
}
用例是这样的,当调用一个需要数组的方法时,您不需要定义数组,而只需执行数组(val1、val2、val3)

然而,IntelliJ给了我堆污染警告。我在某种程度上理解这意味着什么,但我对细节没有太多经验——因此,我想知道我是否可以添加@SafeVarargs,以及这个方法是否真正安全

IntelliJ说:

问题简介参数化堆可能造成的堆污染 第249行的vararg类型

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


K与V一起声明为类的类型参数。不,如果从另一个使用泛型的方法调用它,它是不安全的。下面是一个完整的示例,看起来不错,但引发了一个异常:

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");
    }
}
类实用程序{
公共K[]数组(K…ks){
返回ks;
}
公共K[]其他方法(kk1,kk2){
返回阵列(k1,k2);
}
}    
课堂测试{
公共静态void main(字符串[]args)引发异常{
实用工具util=新实用工具();
//砰!
字符串[]数组=util.otherMethod(“foo”,“bar”);
}
}
当编译器为
otherMethod
创建字节码时,它无法创建正确类型的数组以传递到
array
,因为它不知道
K
的类型。由于类型擦除,它只创建一个带有值的
对象[]
。因此,在
main
中,有一个从
otherMethod
的结果到
String[]
的隐藏转换。。。而这在执行时失败了


如果您直接从真正了解参数类型的代码调用
array
,那么这没关系,因为隐式创建的数组将是正确的类型。

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

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;
}
public K[]otherMethod(K[]parent,K k1,K k2){
列表=新的ArrayList();
addAll(列表,数组(k1,k2));
列表。toArray(母公司);
返回父母;
}
现在,输出取决于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");
    }
}
类测试{
公共静态void main(字符串[]args)引发异常{
实用工具util=新实用工具();
String[]array=util.array(“一”、“二”、“三”);
array=util.otherMethod(数组,“x”,“y”);
printArr(数组);//prints:x y null
实用程序util2=新实用程序();
整数[]intarray=util2.otherMethod(新整数[1],1,2);
printArr(intarray);//prints:null
整数[]intarray=util2.otherMethod(新整数[2],1,2);
printArr(intarray);//打印:1 2
}
静态void printArr(对象[]objArr){
用于(对象o:objArr)系统输出打印(o+“\t”);
}
}

IMO你不需要这种方法,只要使用
whateverArray={val1,val2,val3,…}你能给出堆污染警告的确切细节吗?类型参数
K
声明在哪里?@Luiggi,是的,但它是一个实用程序<代码>K[]键={key1,key2,key3};对象、方法(键)
vs
object.method(数组(key1,key2,key3))-第二个更容易编写,尤其是当你经常这么做的时候。不,它不是。如果需要动态创建这样的数组,可以这样做:
foo.method(newwhich[]{val1,val2,val3,…})。没有必要使用你的实用方法。@LuiggiMendoza:写
foo(数组(a,b,c))
显然比写
foo(新的[]{a,b,c})
要简单得多。谢谢。只要这是唯一(在合理的范围内)可能导致问题的情况,我所做的一切都应该是好的。在这里要非常小心,@DziNeIT。如果这只是一个愚蠢的行为,而你是唯一使用此代码的人,那么继续吧。然而,我知道如果我遇到这样的事情,我会怎么想。不过,这是一个很好的问题,答案也同样不错。:)