使用Java中的varargs创建通用数组的潜在风险是什么?

时间:2016-05-06 07:30:17

标签: java arrays generics variadic-functions

我找到了一种使用varargs和匿名内部类创建通用数组的方法:

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

Java编译器对此代码不产生任何警告,而代码检查(在IntelliJ中)说:

Unchecked generics array creation for varargs parameter

这里发生了什么,为什么会发誓?

2 个答案:

答案 0 :(得分:3)

在内部,您正在创建一个&#34; Object&#34;而不是&#34; C&#34;

的数组

试试这段代码:

 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

你可以看到它们不一样。

这很危险,因为如果你运行这样的东西:

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

你将有一个ClassCastException

  

[Ljava.lang.Object;无法转换为[Ljava.lang.Integer

如果你想创建任何类型的数组,你需要发送类来构造数组,你可以这样做:

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];
}

答案 1 :(得分:1)

代码检查会注意到因为varargs是用数组实现的,而数组不支持泛型。但您可以通过添加以下内容来抑制该警告:

@SuppressWarnings("unchecked")

发生这种情况的原因是它可能导致信息丢失。您可以阅读有关here的更多信息。