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

标签 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

当我们在 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

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

List<Object> test = new ArrayList<Object>();
            test.add("hello");
            test.add(new Integer(34));

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

我确实明白他上面这句话的意思。一些澄清会有所帮助

最佳答案

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

关于通配符:

  • Set<Object>的通用类型恰好是 Object .您可以插入和检索 Object它的实例,但你不能传递 Set<Integer>一个期待 Set<Object> 的方法,因为该方法可能计划添加一个非 Integer反对集合。
  • Set<?>具有未指定的通用类型。一个方法可以从中检索任何东西作为 Object (因为一切都是 Object )并且可以像 hashCode 一样调用通用方法或 toString , 但它不能向集合中添加任何内容。
  • Set ,正如您提到的,是原始类型,不应在新代码中使用。

关于java - 如何在 Java 的泛型(Erasure)中检索类型信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18605074/

相关文章:

iphone - 评估/比较 NSString 与通配符?

java - 查找包含另一个字符串的字符串部分,以及可能的中间单词

java - 在 Linux 上构建 JSCIPOpt(Scip 的 Java 接口(interface))

java - Hibernate/JPA 在 Eclipse 中运行良好,部署时抛出 SchemaManagementException

generics - 在一种情况下将 Kotlin 泛型限制为不为 null

java - 为什么要定义多个导入?

java - 在 Java 中为后台计算创建图形上下文

c++ - 类型索引元组

c# - 通用 KeyValuePair 和类型推断

c# - 在 C# 中使用通配符解析相对路径