Java 8 新特性—类型推断优化

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

理解泛型

在讨论类型推断之间,我们有必要先理解下泛型。

泛型是 Java 1.5 引入的特性,主要目的是增强 Java 程序的类型安全性,同时提高代码的重用性和可读性。比如,在泛型引入之前,所有的集合都是保存 Object 类型的,很容易意外地将错误类型的对象放入集合中,这可能导致运行时异常。

List list = new ArrayList();
list.add("skjava.com");
list.add(1234);

同时,从集合中取出的对象也是 Object 类型的,需要我们显式强制转换为适当的类型:

String str = (String) list.get(0);

通过引入泛型可以解决这两个问题:

  • 泛型通过在编译时提供类型检查,能够减少因为存放错误类型的错误。比如:
List<String> list = new ArrayList<String>();
list.add("skjava.com");
list.add(1234);    // 这是错误的,1234 不为 String 类型
  • 泛型消除显示的强制类型转换,因为编译器能够自动地处理类型转换的细节,比如:
String str = list.get(0);     //不需要再强制类型转换了

当然,除了集合外,泛型还能够泛化方法和类,我们可以创建泛型类或泛型方法,它们可以使用多种类型而不是单一的类型。这样就增加了代码的灵活性和可重用性。

泛型虽好,但是它有一个坑,就是每次定义时都要写明泛型的类型,显得非常冗余,比如:

List<String> list = new ArrayList<String>();
list.add("skjava.com");

我明明在定义变量的时候就已经指明了参数类型,为什么在初始化的时候还要我指定呢?这不显得多余吗?

Java 7 类型推断优化

Java 7 为了解决这个冗余的问题,引入“钻石操作符”(即 <>)用来简化泛型实例的创建过程。钻石操作符 <> 允许编译器根据上下文推断出泛型的类型,从而避免了重复的类型声明。比如:

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

可以优化为:

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

在这里,new ArrayList<> 中的 <> 操作符使得编译器能够自动推断出其类型为 String

一定要注意new ArrayList 后面的“<>”,只有加上这个“<>”才表示是自动类型推断,否则就是非泛型类型的 ArrayList,并且在使用编译器编译源代码时会给出一个警告提示。

但是 Java 7 的类型推断还是有缺陷:

  • 只有构造器的参数化类型在上下文中被显著的声明了,才可以使用类型推断,否则不行,例如:

这里 new ArrayList<>() 需要明确指定类型:

List<String> list = new ArrayList<>();
list.add("skjava.com");
list.addAll(new ArrayList<String>());

Java 8 类型推断优化

为了简化代码的编写,减少冗余信息以及 Lambda 表达式,Java 8 对类型推断进行进一步的优化,主要内容有:

  1. 与 Lambda 表达式和方法引用的协同
  2. Stream API 中的应用

与 Lambda 表达式和方法引用的协同

Java 8 引入 Lambda 表达式极大地简化代码代码量和代码结构,标志着 Java 向函数式编程迈出了重要的第一步。而简写 Lambda 表示的一个依据就是类型推断,它允许编译器根据上下文自动推断 Lambda 表达式的参数类型,它分为目标类型推断和参数类型推断。

更多关于 Lambda 表达式的请阅读:Java 8 新特性—Lambda 表达式

Stream API 中的应用

Java 8 引入 Stream API 极大地提高了 Java 对集合的操作能力,类型推断使得在使用 Stream API 时让代码更加简介和阅读,比如,不使用类型推断:

Stream<String> stream = list.stream();
stream.filter((String s) -> s.startsWith("sike"));

使用类型推断的写法:

list.stream().filter(s -> s.startsWith("sike"));

在这里,编译器能够从上下文推断出 s 的类型是 String

Stream API 支持的链式操作,类型推断在这里也发挥着重要作用,使得这些链式调用更加简洁:

List<String> filteredList = list.stream()
                                .filter(s -> s.startsWith("sike"))
                                .map(String::toUpperCase)
                                .collect(Collectors.toList());

filtermap 和 collect 操作形成了一个操作链,每个操作的输出类型自动成为下一个操作的输入类型,无需显式指定。你说,如果这里需要强制转换得要多麻烦?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值