Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this use of varargs safe?

Tags:

I have a sort of util method to transform a varargs of a type into an array of that type - it looks like this:

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

The use case is so that instead of defining an array when calling a method which requires an array, you can simply do array(val1, val2, val3).

However, IntelliJ gives me heap pollution warnings. I understand what this means to an extent, but I don't have much experience with the specifics - so, I would like to know whether I can add @SafeVarargs and whether this method is actually safe.

IntelliJ says:

  Problem synopsis      Possible heap pollution from parameterized vararg type at line 249

Problem resolution    Make final and annotate as @SafeVarargs

K is declared as the type parameter of a class, along with V.

like image 593
OllieStanley Avatar asked Aug 30 '14 16:08

OllieStanley


People also ask

Is the Varargs parameter safe to modify?

Put simply, the varargs usage is safe if we use them to transfer a variable number of arguments from the caller to the method and nothing more!

What is Varargs?

Varargs is a short name for variable arguments. In Java, an argument of a method can accept arbitrary number of values. This argument that can accept variable number of values is called varargs. The syntax for implementing varargs is as follows: accessModifier methodName(datatype… arg) { // method body }

How does Varargs work in Java?

Syntax of Varargs Hence, in the Varargs method, we can differentiate arguments by using Index. A variable-length argument is specified by three periods or dots(…). This syntax tells the compiler that fun( ) can be called with zero or more arguments. As a result, here, a is implicitly declared as an array of type int[].

What is the use of @SafeVarargs in Java?

@SafeVarargs annotation is used to suppress the unsafe operation warnings at the compile time. Unsafe operation warnings come at the compile time whenever in our code we invoked the method which is having varargs i.e. variable number of arguments.


1 Answers

No, it's not safe - if called from another method which is using generics. Here's a complete example which looks okay, but throws an exception:

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");
    }
}

When the compiler creates the bytecode for otherMethod, it can't create an array of the right kind to pass into array, because it doesn't know the type of K. Due to type erasure, it just creates an Object[] with the values. So in main, there's a hidden cast from the result of otherMethod to String[]... and that fails at execution time.

If you call array directly from code which really knows the types of the arguments, then it's fine, because the implicitly-created array will be of the right type.

like image 157
Jon Skeet Avatar answered Sep 29 '22 14:09

Jon Skeet