合理利用泛型擦除

曾几何时,一直痛恨java的泛型擦除,为了适配老版的jdk,java引入泛型的同时,引入了泛型擦除机制,导致想要获取类中的泛型,需要都个圈子,具体可以看我这篇博客,获取泛型的类
前不久使用Mybatis-plus分页,但发现PO对象不满足接口出参数据,因此需要拼接数据转换成VO对象,但分页信息不变,刚想写个方法适配的,结果发现Mybatis-plus已经考虑到这点了,有个convert方法。具体如下:

    /**
     * IPage 的泛型转换
     *
     * @param mapper 转换函数
     * @param <R>    转换后的泛型
     * @return 转换泛型后的 IPage
     */
    @SuppressWarnings("unchecked")
    default <R> IPage<R> convert(Function<? super T, ? extends R> mapper) {
        List<R> collect = this.getRecords().stream().map(mapper).collect(toList());
      //此处强转,是为了通过setRecords方法对于List<T>的校验。为何不会报错:因为在运行期间IPage<R> 和Ipage<T>是一样的,里面存的类型其实是Object,强转后编译器就认为此时Records里面的类型是R,因此不会报错,运行时也不会报错。
        return ((IPage<R>) this).setRecords(collect);
    }
        /**
     * 设置分页记录列表
     */
    IPage<T> setRecords(List<T> records);

上述方法其实也有多种实现,如下
第一种(不强转)

    @SuppressWarnings("unchecked")
    default <R> IPage<R> convert(Function<? super T, ? extends R> mapper) {
    //此处不说明List集合里面的对象类型,List<T>和List<R>都是List对象,因此转成List可以绕过编译器检测,因为泛型擦除机制,运行时不会校验类型。
 List collect = this.getRecords().stream().map(mapper).collect(toList());
        return this.setRecords(collect);
    }

第二种(强转)

    @SuppressWarnings("unchecked")
    default <R> IPage<R> convert(Function<? super T, ? extends R> mapper) {
    //此处也是通过强转,绕过编译器检测,使其在编译期无法校验泛型的类型。
     List<R> collect = this.getRecords().stream().map(mapper).collect(toList());
        return ((IPage) this).setRecords(collect);
    }

如果你搞懂了上面的例子,你也就能明白下面的例子了

List<String> s = null;
List<Integer> i = null;
//报错
s = (List<Integer>)i;
List tmp = i;
//不报错
s = (List<String>) tmp;
//不报错
s = tmp;	

最后解释下上面的例子,s和i一开始就分别定义成List和List,
因此他们的数据类型是不一致的,所以无法赋值,强转也不行(因为已经显示说明了他们的数据类型了,此处得区别于(IPage®this的情况))。
而经过List tmp = i , 已经将数据类型擦除,绕开了编译器检测,因此 s = tmp
不会报错(可以认为是一种编译器优化,不需要显示强转,由程序员保证类型一致), s = (List<String>) tmp 也不会,直至显示调用get方法转换成String 对象时才会报Integer对象类型无法转换成String类型。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值