java 泛型(类)方法返回值为什么是 Object??

发布于 2022-09-11 15:19:48 字数 1108 浏览 30 评论 0

我认知中,java 虚拟机是不认识泛型类或泛型方法的,所以在编译成字节码的时候,所有的泛型类或泛型方法,都会被转换成普通的类或方法。

例如:

// 泛型类
class Test<T> {
    public T res = null;
    
    public Test(T res){
        this.res = res;
    }
    
    public T get(){
        return this.res;
    }
}

Test t = new Test<String>("泛型类-Test的泛型方法-get");
// 报错
String res = t.get();

编译时类型参数发生替换(类型擦除),也就是编译后的字节码中的代码应该长下面这样:

public class Test {
    private String res = null;
    
    public Test(String res){
        this.res = res;
    }
    
    public String get(){
        return this.res;
    }
}

Test t = new Test("泛型类-Test的泛型方法-get");
// 报错!类型擦除后,为什么调用该方法返回的类型是:Object ?
String t = t.get();

问题就出现在:

Test t = new Test<String>();
// 报错!这边返回的是 Object
String res = t.get();

我很郁闷 .... ,不能理解为什么提供了类型参数后进行方法调用返回的不是提供的类型 String 而是 Object 类型?

然而,在如下场景中,结果却正确了

// 结果正确
Test<String> t = new Test<>();
String res = t.get();

这是为什么??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

萌酱 2022-09-18 15:19:48

可以参考这两个问题思考一下,为什么目前的行为是合理的。

问题一:下面的代码能不能编译通过?
(可以,因为 ArrayList<String> 和 ArrayList<Integer> 都是 List)。

        List list;
        list = new ArrayList<String>();
        list = new ArrayList<Integer>();

问题二:按照你的思路,list.get(0) 的类型应该是什么?

        if (input == 42) {
            list = new ArrayList<String>();
            list.add("magic").
        } else {
            list = new ArrayList<Integer>();
            list.add(42).
        }
        
        // 哪行代码应该能编译通过?
        // Object value = list.get(0);
        // String value = list.get(0);
        // Integer value = list.get(0);
顾挽 2022-09-18 15:19:48

Object是一切的基类,所有的类都是Object,反射使用Object,可以保证通用性。
实际使用的时候,需要基于反射,进行类型的判断和转换。
有把握的进行强制转化,也可以先判断一下(instanceof ),更多的还是根据实际业务进行封装相应的工具类

赏烟花じ飞满天 2022-09-18 15:19:48

泛型本来就是要在声明时候用的。。。

Test<String> t = new Test<>();

这样写编译器才知道t这个引用是个带String泛型的Test引用。

Test t = new Test<String>();

这么写编译器只知道t这个引用指向了带String泛型的一个对象。。。
但是不知道t是带泛型的。。。
而你t.get() 这个方法是t这个引用调用的方法。。。
后一种写法编译器不知道你这个引用带泛型。。。就默认是Object类型。。。

终止放荡 2022-09-18 15:19:48

Test t等同于 Test<Object> t, 返回期待是 Object,但实际也是 String , 所以你需要仅是加上强制转换就好,即

String res = (String)t.get();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文