如何在Java中的泛型(Erasure)中检索类型信息?

bra*_*orm 1 java generics wildcard

通过使用泛型,我们在编译期间检测任何可能的.例如,

List<String> list = new ArrayList<String>();
//list.add(new Integer(45)); This will cause compilation error.
list.add("car");
list.add("bus");
list.add("bike");
String vehicle = list.get(0); //compiler-generated cast
Run Code Online (Sandbox Code Playgroud)

当我们在Java 1.5之前使用原始类型而不是泛型时,它需要显式转换.例如,

List list2 = new ArrayList();
    list.add("car");
    list.add("bus");
    list.add("bike");
    String vehicle = (String)list.get(0); //explicit casting is necessary
Run Code Online (Sandbox Code Playgroud)

但是对于泛型,会发生类型擦除.这是类型信息在运行时丢失.if,就是这样,JVM如何知道它在运行时检索的对象类型,无论是字符串对象还是person对象(上面编译器生成的转换).但这对泛型有效,这可能会导致运行时错误.

List<Object> test = new ArrayList<Object>();
            test.add("hello");
            test.add(new Integer(34));
Run Code Online (Sandbox Code Playgroud)

最后,Joshua Bloch在第115页(第23项,有效的java)中提到了Set<Object>参数化类型,它 是一个可以包含任何类型对象的集合, Set<?>是一个通配符类型,表示一个只能包含某些未知类型的对象的集合,并且Set是一个原始类型,选择退出泛型类型系统.

我明白上述陈述的含义.一些澄清将有所帮助

chr*_*ke- 5

编译器在从泛型方法中检索项时插入转换操作; 这是JVM知道将结果list.get(0)视为a 的唯一方法String.这就是为什么堆污染(将错误类型的对象插入到泛型集合中)可能导致ClassCastException运行时.

关于通配符:

  • Set<Object>的通用类型正是如此Object.您可以从中插入和检索Object实例,但是您无法将a传递Set<Integer>给期望a Set<Object>的方法,因为该方法可能计划将非Integer对象添加到集合中.
  • Set<?>有一个未指定的泛型类型.一个方法可以检索任何东西作为Object(因为一切是Object),并可以调用通用的方法,它喜欢hashCodetoString,但它不能在集添加任何东西.
  • Set如您所述,是原始类型,不应在新代码中使用.

  • 一个漂亮打印集合的方法可能需要一个`Collection <?>`,因为它不需要知道集合内容的类型来调用它们的`toString`.如果你将它声明为`Collection <Object>`,则无法将`Collection <Integer>`传递给它. (2认同)