eclipse不支持泛型_泛型概述(下):泛型实现机制

本文深入探讨了Java泛型的工作原理,包括泛型擦除、自动类型转换以及其与多态的关系。泛型在编译期帮助进行类型校验和转换,但在运行期,所有泛型类底层仍使用Object。编译器在泛型的实际类型参数基础上进行类型转换,实现了编译期的安全性和运行期的多态性。
摘要由CSDN通过智能技术生成

编写:bravo1988

校审:养兔子的大叔

上篇提到泛型可以看做是对变量类型的抽取,它把原本必须确定的对象类型也弄成了变量,最终得到代码模板

但是,敏感的读者马上就会发现这tm是个悖论啊:对象类型不确定,JVM怎么创建对象啊!

要回答这个问题,我们必须了解Java的两个阶段:编译期、运行期。你可以理解为Java代码运行有4个要素:

  • 源代码
  • 编译器
  • 字节码
  • 虚拟机

也就是说,Java有两台很重要的机器,编译器和虚拟机。

在代码编写阶段,我们确实引入了泛型对变量类型进行泛化抽取,让类型是不特定的(不特定的即通用的),从而创造了通用的代码模板,比如ArrayList<T>:

public class ArrayList<T> {
    
    private T[] array;
    private int size;
    public void add(T e) {...}
    public void remove(int index) {...}
    public T get(int index) {...}
}

模板定好后,如果我们希望这个ArrayList只处理String类型,就传入类型参数,把T“赋值为”String,比如ArrayList<String>,此时你可以理解为代码变成了这样:

public class StringArrayList {
    
    private String[] array;
    private int size;
    public void add(String e) {...}
    public void remove(int index) {...}
    public String get(int index) {...}
}

所以add(1)会编译报错。

但事实真的如此吗?

我们必须去了解泛型的底层机制。

泛型擦除与自动类型转换

我们来研究以下代码:

public class GenericDemo {
    

    public static void main(String[] args) {
    
        UserDao userDao = new UserDao();
        User user = userDao.get(new User());
        List<User> list = userDao.getList(new User());
    }

}

class BaseDao<T> {
    

    public T get(T t){
    
        return t;
    }

    public List<T> getList(T t){
    
        return new ArrayList<>();
    }
}


class UserDao extends BaseDao<User> {
    

}

class User{
    

}

编译得到字节码:

69418160603820014284a9bf3cf3ec54.png

通过反编译工具,反编译字节码得到:

public class GenericDemo {
    
	// 编译器会为我们自动加上无参构造器
    public GenericDemo() {}

    public static void main(String args[]) {
    
        UserDao userDao = new UserDao();
        /**
         * 两点变化:
         * 1.原先代码是 User user = userDao.get(new User());
         *   编译器根据泛型类型User,帮我们强转了
         * 2.List<User>的泛型被擦除了,只剩下List
         */
        User user = (User)userDao.get(new User());
        java.util.List list = userDao.getList(new User());
    }
}

class BaseDao {
    

    BaseDao() {}
    
	// 编译器编译后的字节码中,其实是没有泛型的,泛型T其实底层还是JDK1.5的Object
    public Object get(Object t)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值