java - 泛型混淆 : deceiving the compiler

标签 java generics

考虑一段代码:

public class GenericsConfusion {
    public static <T> Class<T> get(Class<T> clazz) {
        Map<Class, Class> map = new HashMap<Class, Class>();
        map.put(Integer.class, String.class);
        return map.get(clazz);
    }

    public static void main(String[] args) {
        Class<Integer> clazz = get(Integer.class);
        System.out.println(clazz);
    }
}

它可以完美地编译和运行。这个想法是在 get 方法中返回与输入类具有相同类型参数的类。但由于 map 的存在,它被打破了。 是的,我知道在运行时类型参数信息被删除,所以没有类型参数这段代码是完全有效的。我也知道我可以通过指定 Map<Class<T>, Class<T>> 来修复它但事实是,在方法签名中我有类型参数,它们在编译时对我没有帮助。

这是对某些概念的误用吗?

还是Java泛型的缺点?

或者它完全没问题,我误解了类型参数的概念?

最佳答案

原始类型,例如 ClassMap(与 Class<...>Map<..., ...> 相对),绕过泛型的类型检查。你甚至可以这样写:

final Class<Integer> whoops = (Class) String.class;

这是类型系统中一个不幸的弱点。它最初包含在 Java 5(引入了泛型)中,以与在以前版本下编写的代码兼容。

在大多数情况下,您可以通过避免使用原始类型来避免这种弱点。您的编译器应该警告您。

不幸的是,在各种情况下原始类型基本上是不可避免的(由于 .getClass() 的特殊类型;由于我们只能写(例如)Map.class 而不是 Map<String, String>.class(或 Map.<String, String>class );由于删除和反射等);但令人高兴的是,正如您所指出的,您的情况似乎不是其中之一。

关于java - 泛型混淆 : deceiving the compiler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26129973/

相关文章:

java - 服务小程序异常 : No servlet class has been specified

Java 3-SUM 代码表现异常

java - Google Web Toolkit 入门应用程序不工作

java - 中缀到后缀

java - Java+MySQL 中的小型网络应用程序 : GAE vs EC2

Java Swing - 如何使用泛型在 Swing 组件上创建实用程序类

java - 如何在Java中创建通用数组?

go - 接受 channel 和 slice 的通用函数

java - 公共(public)类 Extra<BASE> 扩展 BASE

java - 参数隐藏类型