Java Generics:如果在编译时未擦除类型的示例

时间:2017-05-07 23:26:49

标签: java generics erasure

在Java中,泛型类型在编译时被擦除,而Object代替所有泛型参数,并完成隐式转换。这样做的原因是为了保持向后兼容性,如here所述。任何人都可以在Java 1.5之前提供代码示例,如果Java 1.5在编译时没有擦除类型,那么这会在运行时引起问题吗?

1 个答案:

答案 0 :(得分:1)

我认为你误解了类型擦除的目的,首先 - 类型擦除并不是为了避免运行时异常(,但它意味着避免任何运行时性能损失,更多信息即将到来...... )和其次 - 在Java SE 5之前没有“泛型”,因此不存在“类型擦除”的问题。

阅读here关于类型擦除的目的:

  

泛型被引入Java语言以提供更紧密的类型   在编译时检查并支持通用编程。至   实现泛型,Java编译器将类型擦除应用于:

     
      
  • 如果类型参数是无界的,则将泛型类型中的所有类型参数替换为其边界或对象。生成的字节码,   因此,只包含普通的类,接口和方法。
  •   
  • 如有必要,插入类型转换以保护类型安全。
  •   
  • 生成桥接方法以保留扩展泛型类型中的多态性。
  •   
     

类型擦除确保不会为参数化创建新类   类型;因此,泛型不会产生运行时开销

因此,泛型中“类型擦除”的主要目的之一是避免任何运行时性能损失,因为所有类型参数在编译时都会根据类型参数进行解析和验证,因此在运行时JVM需要浪费任何CPU周期。

参见下面的代码,它显示在编译之后,类型被解析,并且JVM将解释的最终字节码不会有任何类型参数。

编辑之前:

import java.util.Arrays;
import java.util.List;

public class TypeErasureExample {
    public static void main(String[] args) {
        List<String> stringList = Arrays.asList(new String[]{"a", "b", "c"});
        List<?> numberList = Arrays.asList(new Integer[]{1, 2, 3});

        System.out.println(stringList);
        System.out.println(numberList);
    }
}

编译后(反编译o / p):

import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;

public class TypeErasureExample
{
  public static void main(String[] paramArrayOfString)
  {
    List localList1 = Arrays.asList(new String[] { "a", "b", "c" }); // Notice "List<String>" is converted to "List", this is what type erasure does.
    List localList2 = Arrays.asList(new Integer[] { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3) }); // Notice "List<?>" is converted to "List", this is what type erasure does.

    System.out.println(localList1);
    System.out.println(localList2);
  }
}