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.
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!
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 }
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[].
@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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With