java泛型面试

泛型本质

本质就是语法糖,语法糖就是编译期间发生的,编译之后就没了踪迹。像c++有模板类,java的泛型也达到了类似的效果,但是他们实现的本质是不一样的。因为java有泛型擦除,编译之后就没了相关信息,比如List<Integer>和List<String> 是一样的类型,都是List。在c++里就不一样了,对应两个不同的类(如果有叫List的模板类)。

泛型擦除

既然java语言增加了泛型功能,当然我们推荐使用泛型了,使用泛型一方面代码更加健康,另一方面可读性也更好。上面我们也说了java的泛型是语法糖,编译之后泛型信息会丢失,这个我们可以通过字节码反编译看到。所以它只保证编译时的安全性检测,运行时就不保证了。比如我们可以通过反射把Integer放到List<String>中。
为什么不像c++那样,为啥要泛型擦除呢?具体详细原因不清楚,但有一点,避免了大量临时类的产生,节省资源和空间可能是一方面的考虑吧。

获取泛型信息

类型擦除是不是无条件的?所有泛型相关的信息都会被擦除吗?显然不会,不然class怎么会提供 getGenericSuperclass、getGenericInterfaces 等方法来获取泛型相关的信息呢?所以在有些情况下泛型信息是会被保存下来的。
既然类型擦除是为了避免产生大量的临时类,那我们能不能显式的以生成临时类的方式让泛型信息留下呢?

匿名类

比较简单的方式 List<DemoBean> list = new ArrayList<DemoBean>(){};
泛型信息
需要注意的是 new ArrayList<DemoBean>(){} 和new ArrayList<DemoBean>() 不是一回事,前面是定义了一个匿名内部类,它的类型并不是ArrayList,而是动态生成的GenericInfo$1的内部类,它的父类是ArrayList<DemoBean>,我们可以看到里面的泛型信息并没有被擦除。后面的就是我们常用的变量初始化了,jdk7以上推荐new ArrayList<>()这样的方式,里面不需要类型信息,jdk自己可以推断出来。

类定义

这种方式其实和上面的匿名类一样,就是在定义泛型类的时候泛型限定了类的信息。
我们又定义了两个类 :DemoBean2 <T> 和 DemoBean3 extends DemoBean2<DemoBean>
这时候DemoBean3的父类的泛型信息就可以获取的到。
在这里插入图片描述

通配符

泛型通配符: <? extends T> 和<? super T>
二者区别,这个很容易弄混。个人的记忆是从左往右理解,<? extends T> 表示 继承于T的类 是上届的限定,<? super T>表示 是T的父类的类(即T是子类)是下界的限定。 使用时注意 <? extends T>用于接收数据,此写法的泛型集合不能使用add方法,<? super T>不能使用get方法,用于频繁往里插入的场景。即PECS(Producer Extends Consumer Super)原则
Java 的泛型擦除和运行时泛型信息获取

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值