转换为不同于实际类的泛型类型时,没有ClassCastException [英] No ClassCastException when casting to generic type different to actual class

查看:72
本文介绍了转换为不同于实际类的泛型类型时,没有ClassCastException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些看起来像这样的代码(对方法 get 的否定测试的一部分):

I have some code which looks something like this (part of a negative test of the method get):

import java.util.*;
public class Test {
    Map<String, Object> map = new HashMap<>();
    public static void main (String ... args) {
        Test test = new Test();
        test.put("test", "value"); // Store a String
        System.out.println("Test: " + test.get("test", Double.class)); // Retrieve it as a Double
    }

    public <T> T get(String key, Class<T> clazz) {
        return (T) map.get(key);
    }

    public void put(String key, Object value) {
        map.put(key, value);
    }
}

我期望它会抛出 ClassCastException ,但它会成功打印:

I was expecting it to throw a ClassCastException but it runs through successfully printing:

Test: value

为什么不抛出?

推荐答案

在删除类型参数(类型擦除)后,考虑类的外观是有益的:

It is instructive to consider what the class looks like after removing type parameters (type erasure):

public class Test {
    Map map = new HashMap();
    public static void main (String ... args) {
        Test test = new Test();
        test.put("test", "value");
        System.out.println("Test: " + test.get("test", Double.class));
    }

    public Object get(String key, Class clazz) {
        return map.get(key);
    }

    public void put(String key, Object value) {
        map.put(key, value);
    }
}

这将编译并产生与您看到的相同的结果。

This compiles and produces the same result that you see.

棘手的部分是这一行:

System.out.println("Test: " + test.get("test", Double.class));

如果您已这样做:

Double foo = test.get("test", Double.class);

然后在类型擦除后,编译器将插入强制类型转换(因为在类型擦除后 test.get()返回 Object ):

then after type erasure the compiler would have inserted a cast (because after type erasure test.get() returns Object):

Double foo = (Double)test.get("test", Double.class);

类似地,编译器也可以在上述行中插入强制类型转换,如下所示:

So analogously, the compiler could have inserted a cast in the above line too, like this:

System.out.println("Test: " + (Double)test.get("test", Double.class));

但是,它不会插入强制类型转换,因为强制类型转换不需要编译和转换行为正确,因为字符串串联( + )在所有对象上的工作方式相同;它只需要知道类型是 Object ,而不是特定的子类即可。因此,在这种情况下,编译器可以省略不必要的强制转换。

However, it doesn't insert a cast, because the cast is not necessary for it to compile and behave correctly, since string concatenation (+) works on all objects the same way; it only needs to know the type is Object, not a specific subclass. Therefore, the compiler can omit an unnecessary cast and it does in this case.

这篇关于转换为不同于实际类的泛型类型时,没有ClassCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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