对泛型参数类型的错误转换不会在Java中引发ClassCastException [英] A bad casting to Generics parameter type does not throw ClassCastException in Java

查看:151
本文介绍了对泛型参数类型的错误转换不会在Java中引发ClassCastException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我有一个比较深奥的问题。我正在尝试创建一个有点通用但类型化的属性收集系统。它依赖于似乎是错误的核心假设。该代码说明了这个问题:

So, I have rather esoteric question. I'm trying to create a somewhat generic, but typed property collection system. It's reliant on a core assumption that seems to be erroneous. The code illustrates the issue:

import java.lang.Integer;

public class Test {
    private static Object mObj = new String("This should print");

    public static void main(String[] args ) {
    String s = Test.<String>get();
    System.out.println(s);

        try {
        // actual ClassCastException reported HERE
        int i = Test.<Integer>get();
    } catch ( ClassCastException e ) {
        System.out.println("Why isn't the exception caught earlier?");
        }

        int i2 = getInt();
    }

    public static <T> T get() {
    T thing = null;
    try {
        // Expected ClassCastException here
        thing = (T)mObj;
    } catch ( ClassCastException e ) {
        System.out.println("This will *not* be printed");
    }
    return thing;
    }

    // This added in the edit
    public static Integer getInt() {
    return (Integer)mObj;
    }
}

在编译并运行输出后,

This should print
Why isn't the exception caught earlier?

在静态方法 get中,我尝试转换为通用参数类型T。基础成员(mObj)是String类型的。在第一次调用中,Generic参数为兼容类型,因此应用程序将适当地打印字符串。

In the static method "get", I'm attempting to cast to the generic parameter type T. The underlying member (mObj) is of String type. In the first invocation, the Generic parameter is of compatible type, so the app prints the string appropriately.

在第二次调用中,Generic参数的类型为Integer。因此,get方法中的强制转换应失败。而且我希望它会引发ClassCastException(打印语句这将*不*将被打印。)但这不是发生的情况。

In the second invocation, the Generic parameter is of type Integer. Thus, the cast in the get method should fail. And I would hope it would throw a ClassCastException (printing the statement "This will *not* be printed".) But this isn't what happens.

相反,在尝试将返回值分配给变量 i时,之后引发强制转换异常。这里的问题是:

Instead, the casting exception is thrown after the get method returns when the returned value is attempted to be assigned to the variable "i". Here's the question:

此延误转换错误的解释是什么?

What is the explanation for this delayed casting error?

**编辑**
为了乐趣和完整性,我添加了一个非通用的getInt方法来说明我希望获得的响应。

** EDIT ** For the sake of fun and completeness, I added a non-generic getInt method to illustrate the response I was hoping to get. Amazing what happens when the compiler knows type.

推荐答案

这是因为 get 方法(应生成编译器警告)是未经检查的强制转换。调用 thing =(T)mObj; 时,编译器不知道 T 是什么,因此它无法确定

It's because the cast in the get method (which should generate a compiler warning) is an unchecked cast. The compiler does not know what T is when you call thing = (T) mObj; so it cannot know if the cast should not compile.

编译后,由于类型擦除,生成的字节码将调用方法 get 返回 Object (已删除 T 并替换为 Object ),并将类型转换简单地转换为:

After compilation, and due to type erasure, the bytecode generated invokes the method get which returns an Object (T is erased and replaced with Object) and the cast is simply translated to:

Object thing = null;
try {
    thing = mObj;

之后执行检查,结果从 get 方法,即 int i = Test。< Integer> get(); 等效于:

The check is being done after the result is returned from the get method, i.e. int i = Test.<Integer> get(); is equivalent to:

Object o = Test.get();
int i = ((Integer) o).intValue();

这篇关于对泛型参数类型的错误转换不会在Java中引发ClassCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆