T ...(泛型vararg参数)在编译时真的被剥离到Object []吗?

Mer*_*Mer 7 java generics variadic-functions

(我将在这里使用T来引用泛型参数,在参数化类中使用.)

我读到T...当用作参数时潜在的堆污染源的原因是编译器正常(不允许T[]数组)规则和允许T...(这是varargs,因此通常由varargs翻译)内部规则T[],除了泛型不允许)作为参数通过在内部实现它,就像它是一个原始类型,将其转换为数组Object[].

所以我写了一些代码来验证这一点,将这个概念融入我的记忆中.

我把T...t一个方法作为一个参数,然后System.out.println'd t.getClass[].我期望得上课Object[],但相反,我上了T[]课.

因此,似乎编译器正在转换T...tT[]内部,而不是转换为Object[].

例如

 public class MyClass<T>{
 public void method(T...t)
 {
    System.out.println(t.getClass().getName());  //for MyClass<String>, this gives me  
                                                 //[Ljava.lang.String

 }
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么?如果编译器没有在内部转换泛型varargs参数Object[],它如何失去类型安全性并作为堆污染的潜在来源?

use*_*751 10

void method(T... t)
Run Code Online (Sandbox Code Playgroud)

转换为

void method(Object[] t)
Run Code Online (Sandbox Code Playgroud)

所以你所听到的是正确的.但是:

Integer a = 1, b = 2, c = 3;
method(a, b, c);
Run Code Online (Sandbox Code Playgroud)

转换成:

Integer a = 1, b = 2, c = 3;
method(new Integer[] {a, b, c});
Run Code Online (Sandbox Code Playgroud)

所以运行时类型tInteger[],即使它的声明类型(编译后)是Object[].

  • @Mer泛型在编译*后被丢弃*,因为JVM不需要关心它们.这并不意味着他们什么都不做.特别是,编译器会检查您是否没有弄乱泛型. (4认同)
  • @Mer:想象一下你有一个方法需要`T ... args`(`args`有类型`T []`)并简单地返回`args`,类型为`T []`.现在通过传递给这个varargs函数并获得结果,你已经完成了`new T [...]`,这在Java中是不允许的.如果你理解为什么不允许使用`new T [...]`,以及为什么你不能用`(T [])new Object [...]`安全地替换它,你会明白为什么这是不安全的. (2认同)