【问题标题】:Is T... (generics vararg parameter) really stripped down to Object[] at compile time?T...(泛型 vararg 参数)真的在编译时被剥离为 Object[] 吗?
【发布时间】:2014-10-28 14:57:13
【问题描述】:

(这里我将使用 T 来指代泛型参数,用于参数化类。)

我读到T... 用作参数时是堆污染的潜在来源的原因是编译器对正常(不允许T[] 数组)规则进行了例外处理,并允许T... (这是可变参数,因此通常会在内部通过可变参数规则转换为T[],除非泛型不允许这样做)作为参数,通过在内部实现它就好像它是原始类型一样,将其转换为Object[] 代替。

所以我写了一些代码来验证这一点,把这个概念牢牢地印在我的记忆中。

我将T...t 作为方法的参数,然后将System.out.println'd t.getClass[]。我希望得到Object[] 的课程,但我得到了T[] 的课程。

因此,编译器似乎在内部将T...t 转换为T[],而不是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

 }

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

【问题讨论】:

  • 你是怎么调用这个方法的? method("string", "another");?
  • 是的。 MyClass mc = new MyClass(); mc.method("what","the","something");
  • 如果去掉类型注解(只是MyClass mc)会变成Object[]吗?

标签: java generics variadic-functions


【解决方案1】:
void method(T... t)

转换成

void method(Object[] t)

所以你听到的是正确的。 但是

Integer a = 1, b = 2, c = 3;
method(a, b, c);

转换成:

Integer a = 1, b = 2, c = 3;
method(new Integer[] {a, b, c});

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

【讨论】:

  • 我想组件类型是从编译器的泛型类型注释中获取的?还是从实际论证中推断出来的?
  • 谢谢!但是,如果编译的类型是void method(Object[] t),为什么编译器仍然拒绝方法调用MyClass mc = new MyClass(); mc.method("what","the","something",4);带有编译器消息:“GenericsReview 类型中的方法 method(String...) 不适用于参数 (String, String, String, int)”(拒绝 int 不是自动装箱失败,因为mc.method("what","the","something",new Integer(4)); 也被拒绝。)
  • @Thilo 我猜(我不确定)它是从实际参数中推断出来的。也许尝试用Object 替换T,看看t instanceof Integer[] 是否为真。
  • @Mer 泛型在编译后被丢弃,因为 JVM 不需要关心它们。这并不意味着他们什么都不做。特别是,编译器会检查你没有弄乱泛型。
  • @Mer:假设你有一个方法,它接受T... argsargs 的类型为T[])并简单地返回args,作为T[] 类型。现在通过传递给这个 varargs 函数并获得结果,您已经完成了new T[...],这在 Java 中是不允许的。如果您了解为什么不允许使用new T[...],以及为什么不能安全地将其替换为(T[])new Object[...],您就会明白为什么这是不安全的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多