java - 使用 Java 泛型进行类型强制

标签 java generics

这里我有以下代码:

public final class Generics {
    private Generics() {}

    public static <T> T unchecked(Object obj) {
        return (T)obj; //unchecked cast warning
    }

    public static void main(String[] args) {
        //correct
        ArrayList<String> str = new ArrayList<String>();
        str.add("Hello");
        str.add("World");
        System.out.println(str);

        //"correct" - not type safe at all but due to type erasure this is almost legal
        ArrayList<Object> obj = Generics.<ArrayList<Object>>unchecked(str);
        obj.add(1);
        System.out.println(obj);

        //obviously wrong but still compiles (ClassCastException at runtime)
        Exception except = Generics.<Exception>unchecked(str);
        System.out.println(except);
    }
}

通常是 ArrayList<Object> obj = (ArrayList<Object>)str 形式的转换将是致命的编译错误,因为这会违反使用该列表的预期。 (您可以将不是字符串的对象插入到仅包含字符串的列表中)

这种情况下的“未检查”警告是什么,unchecked() 是如何使用的?方法不同于直接转换引用?这如何绕过编译器的类型检查?

最佳答案

What is the "unchecked" warning in this scenario

未经检查的转换只是简单的转换,实际上不会在字节码中产生 checkcast 指令。

public static <T> T unchecked(Object obj) {
    return (T)obj; //unchecked cast warning
}

在这里,这是一个未经检查的转换,因为 T 的删除是 Object,所以它实际上是一个空操作,因为 obj 已经是一个对象

但有害的是,在调用站点插入了一个已检查的转换:

Exception except = Generics.<Exception>unchecked(str);
               // ^ cast here!

删除后,有效执行的代码是:

Exception except = (Exception) Generics.unchecked(str);

这会失败并出现 ClassCastException。但是您不会收到警告,因为该方法的返回类型表明这将是安全的,因此编译器相信它在调用站点是安全的。

调用站点无法知道 unchecked 方法正在做一些危险的事情。事实上,它能做的唯一安全的事情就是返回 null。但是编译器不会考虑它是否这样做:它只是简单地接受 unchecked 方法的声明。

how is the use of the unchecked() method different from casting the reference directly?

这不是,真的。唯一的区别是您是通过 Object 隐式转换的。所以虽然这不能编译:

Exception except = (Exception) str;

这样做:

Exception except = (Exception) (Object) str;

并且会在编译时失败并返回相同的 ClassCastException

关于java - 使用 Java 泛型进行类型强制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50777844/

相关文章:

java - 流口水为什么 StatefulKnowledgeSession 有不同的知识库

typescript - typescript 中类内的类型或接口(interface)

c# - 将 IList<string> 转换为 IList<object> 在运行时失败

java - 如何使用泛型类型类获取用户输入并转换为所需类型?

java - 在 java 中删除对象之前检查对象是否在某处使用

java - JNI 和 C++ - UnsatisfiedLinkError

java - Android MediaPlayer - 位置在缓冲时跳过

typescript - 如何在 TypeScript 中创建一个适用于数字和字符串的通用加法运算符

c# - 检查对象是否为 System.Generic.List<T>,对于任何 T

java - 如何将字符串转换为日期对象?