文章目录

  • 简介
  • 类型的显示使用
  • Stream中的类型推断
  • 类型推断中变量名字的重要性
  • 类型推断对性能的影响
  • 类型推断的限制
  • 总结

简介

java是强类型的编程语言,每个java中使用到的变量都需要定义它的类型,否则会编译失败。强类型语言的好处就是可以尽可能的在编译期间就发现代码中可能出现的问题,从而减少在运行时出现问题的可能性。

相对的,强类型语言的缺点就是不那么的灵活多变,写起来比较冗余。

JDK8之前,java是不支持类型推断的,在JDK8中,引入了lambda表达式,从此类型推断产生了。

本文将会讲解类型推断在lambda表达式中的最佳实践和在使用中应该注意的事项。

更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程

更多内容请访问www.flydean.com

类型的显示使用

假如我们定义了一个CustUser类,并且其中有age和name两个属性:

@Data
@AllArgsConstructor
public class CustUser {int age;String name;
}

看下我们怎么在Stream中显示使用类型:

public static void testStream(){Stream.of(new CustUser(10,"alice"), new CustUser(20,"bluce")).forEach( (CustUser custUser)-> System.out.println(custUser.name));}

上面的例子中,我们构建了一个CustUser类型的Stream,并在forEach方法中对CustUser进行处理。

forEach接收一个Consumer对象,Consumer需要实现void accept(T t)方法。因为Consumer函数接口,我们可以使用lambda表达式来替换。

这里,我们显示传入一个CustUser类型。代码编译是没有问题的,但是看起来复杂了点。接下来我们看下怎么在Stream中使用类型推断。

Stream中的类型推断

上面的例子,我们可以改写成这样:

public static void testInference(){Stream.of(new CustUser(10,"alice"), new CustUser(20,"bluce")).forEach(custUser-> System.out.println(custUser.name));}

这里我们并没有定义custUser的类型,但是java可以从Stream中的类型推断出来。所以这样写是没有问题的,可以正常通过编译。

类型推断中变量名字的重要性

上面的例子中,我们将变量的名字定义为custUser,查看代码的人一眼就可以看出来这个参数表示的是CustUser类型的custUser参数。

名字写的有意义可以很大程度上提升代码的可读性和可维护性。如果你这样写:

forEach(u-> System.out.println(u.name)

虽然代码变得更短了,但是失去了可读的意义,一眼看过去,大家并不知道你这个u代表的是什么,从而影响了代码的可读性。

所以变量名的定义一定要有意义。

类型推断对性能的影响

类型推断是个好东西,那么有同学会问了,类型推断对于java的性能会有影响吗?

我们可以把java分成编译和运行两部分。类型推断是在编译期间做的事情,可能使用类型推断会延长代码编译的时间,但是对运行时的效率是没有影响的。

一般来说,我们关注程序的性能问题是在运行时而不是编译时,所以类型推断对性能是没有影响的。

类型推断的限制

java虽然有类型推断,但是这个推断是有一定的限制的,它并不能够像人一样去思考,但是也已经足够智能了。下面我们举个例子:

public static Comparator<CustUser> createUser1(){return (CustUser user1, CustUser user2) -> user1.getAge() - user2.getAge();}

上面的例子中,我们需要创建一个Comparator,使用lambda表达式我们可以生成一个Comparator。

Comparator需要实现方法int compare(T o1, T o2),传入两个参数,返回一个int。

上面例子中,我们显示指定了两个参数的类型是CustUser,编译没有问题。

如果不显示指定CustUser类型可以吗?

public static Comparator<CustUser> createUser2(){return (user1, user2) -> user1.getAge() - user2.getAge();}

答案也是可以的。这个例子中,我们并没有传入user1,user2,java是怎么找到user1和user2的类型呢?

注意,上面的例子中,我们定义了返回类型是CustUser的,Java通过这个返回类型来推断出传入的实际类型就是CustUser的。是不是很智能。

如果我们将上面的return语句拆分成两条,会出现问题问题呢?

Comparator comparator=(user1, user2) -> user1.getAge() - user2.getAge();

这时候就会编译报错,说找不到getAge方法。这是因为我们返回的Comparator并没有指明类型,所以默认情况下是Object类型。Object类型并没有getAge方法,所以报错。

我们可以这样改写:

Comparator<CustUser> comparator=(user1, user2) -> user1.getAge() - user2.getAge();

编译完成,没有错误。

总结

除了JDK8中引入的lambda表示中使用了类型推断,其实JDK10中的var本地变量类型也是用到了类型推断,详请参考JDK10的新特性:本地变量类型var。

本文的例子https://github.com/ddean2009/
learn-java-base-9-to-20

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/java-type-inference-lambda/

本文来源:flydean的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

Java中的类型推断和lambda表达式相关推荐

  1. C#中的委托和Java中的“委托”(Java8 lambda表达式)

    Java8中新增了有关对lambda表达式的支持,其本质是一种编译阶段的语法糖,效果是双向的,代码看似简洁的前提下牺牲了部分可读性. 我们可以尝试实现一些有意思的东西,先来看段C#委托(delegat ...

  2. 用通俗易懂的大白话搞明白Java里的函数式编程和Lambda表达式

    今天,用通俗易懂的大白话来彻底搞明白Java里的函数式编程和Lambda表达式 为什么引入函数式编程,lambda表达式? 大家都知道,JDK1.8引入了函数式编程,lambda表达式. 那有没有想过 ...

  3. 0202年了,还没有用上Java函数式编程!!!——Lambda表达式

    0202年了,还没有用上Java函数式编程!!!--Lambda表达式 函数式编程是什么 命令式编程(Imperative) 声明式编程(Declarative) 函数式编程(Functional) ...

  4. Java 8之前和之后的Lambda表达式

    Java 8之前和之后的几个示例程序的快速指南.Java8 Concepts进一步简化了代码,并且对核心逻辑(而不是语法)产生了深远影响. 1.简介 在本教程中,我们将学习如何使用Java 8编写程序 ...

  5. Java 7的类型推断

    每个优秀的程序员都喜欢编写简洁但有效且经过优化的代码. 类型推断是JDK 7中引入的一种方法,它肯定会为您带来更少键入的好处. 您以以下方式使用Java代码已有很长时间了. 但是,在初始化Collec ...

  6. C++11中新特性之:lambda 表达式

    首先摆出Lambda表达式语法 lambda-expression: lambda-introducer lambda-declaratoropt compound-statement lambda- ...

  7. IntelliJ Idea中使用Java8新特性lambda表达式

    环境: 环境变量JAVA_HOME配置jdk1.8 idea配置支持lambda: File -> Project Structure -> Modules ->  Language ...

  8. java中map转为json数据_Java技术-将java中Map类型数据转化为json数据并以Ajax形式返回...

    Java技术-将java中Map类型数据转化为json数据并以Ajax形式返回html 1.自定义工具类(简单易用)-下面是我写的一个简单的工具类前端 package com.test.util; i ...

  9. java中的类型擦除type erasure

    文章目录 简介 举个例子 原因 解决办法 总结 java中的类型擦除type erasure 简介 泛型是java从JDK 5开始引入的新特性,泛型的引入可以让我们在代码编译的时候就强制检查传入的类型 ...

最新文章

  1. linux安装vi 插件,Ubuntu上Vim安装NERDTree插件的详细操作步骤
  2. JS详细入门教程(上)
  3. 使用windbg排查一个内存溢出的问题
  4. 绝不能放进微波炉的10样东西,最后一个太意外
  5. 局域网共享问题全方位解决
  6. 职场新人的入门法则:少想、多做、立即执行!
  7. 将截断字符串或二进制数据。
  8. 引用的一个JS组件,JCombo 0.9
  9. 创建高质量Python工程(1)-如何设计结构清晰的目录结构(转)
  10. 让 ADO.NET 2.0 的 SqlCommand 和 SqlDataAdapter 合作
  11. 动词变名词的变化规则_英语单词词性转换规则大全
  12. 概率论:概率及概率公式
  13. 笔记本安装Ubuntu9.04.图文并茂
  14. 杂记二 · 永远不服输
  15. chrome 插件 —— Volume Control 调节声音
  16. GO项目性能优化大赏
  17. php面试题3---php面试题系列
  18. java进阶笔记之常用(通用)Map(Hash,Tree,Linked,Properties等)
  19. 2021年 985 网络空间安全专业 保研路
  20. Hibernate查询性能优化技巧

热门文章

  1. 停止oracle执行session,Oracle 强制中止正在执行的SQL语句
  2. python输出奇数数字序位_python对输出的奇数偶数排序实例代码
  3. 0x5f3759df的数学原理
  4. HDU4622(后缀自动机)
  5. C++中placement new操作符(经典)
  6. 【项目介绍】搜索引擎
  7. 高级数据结构与算法 | 哈希 :哈希冲突、负载因子、哈希函数、哈希表、哈希桶
  8. 2022新年重磅技术分享|深入理解Linux操作系统
  9. JavaScript基本语法(续)
  10. 指定父对象和信号与槽