What are the potential risks of creating a shared array with varargs in Java?

I found a way to create a shared inline array with varargs and an anonymous inner class:

import java.util.Arrays; import java.util.Objects; public class GenericArrayCreate<C> { public void method() { C[] ans = new Object() { C[] c(int length, C ... cs) { return Arrays.copyOf(cs, length); }}.c(10); System.out.println(ans.length); System.out.println(Objects.toString(ans)); } public static void main(String[] args) { new GenericArrayCreate<Class<? extends Integer>>().method(); } } 

The Java compiler does not raise any warnings in this code, and the code check (in IntelliJ) says:

 Unchecked generics array creation for varargs parameter 

What is going on here and why does it swear?

+5
source share
2 answers

Inside, you create an array of "Object" instead of an array of "C"

Try this code:

  public static <C> C[] method(int number) { return new Object() { C[] create(int length, C ... cs) { return Arrays.copyOf(cs, length); } }.create(number); } public static void main(String[] args) { System.out.println(Main.<Integer>method(10)); System.out.println(new Integer[10]); } 

[Ljava.lang.Object; @ 6bc7c054

[Ljava.lang.Integer; @ 232204a1

As you can see, they do not match.

This is dangerous because if you run something like this:

  public static void main(String[] args) { Integer[] integerArray1 = Main.<Integer>method(10); Integer[] integerArray2 = new Integer[10]; } 

And you will have a ClassCastException

[Ljava.lang.Object; cannot be applied to [Ljava.lang.Integer

If you want to create any array, you need to send a class to build the array, you can do it as follows:

 public static <C> C[] method(Class<C> clazz, int number) { return (C[]) Array.newInstance(clazz, number); } public static void main(String[] args) { Integer[] integerArray1 = Main.<Integer>method(Integer.class, 10); Integer[] integerArray2 = new Integer[10]; } 
+3
source

Checking the code will notice that since varargs are implemented using an array, and the array does not support generics. But you can suppress this warning by adding the following:

 @SuppressWarnings("unchecked") 

The reason why this happens can lead to loss of information. You can learn more about this here .

+1
source

All Articles