详解Java8中的lambda表达式、::符号和Optional类

 更新时间:2021年04月02日 11:27:20   作者:WAXXD  
这篇文章主要介绍了Java8中的lambda表达式、::符号和Optional类,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

Java8中的lambda表达式、::符号和Optional类

 0. 函数式编程

    函数式编程(Functional Programming)属于编程范式(Programming Paradigm)中的用语,此外还有命令式编程(Imperative Programing)等,有兴趣的同学可以自行了解,我们这里大概解释一下函数式编程,在函数式编程中,输入一旦确定了,输出都确定了,函数调用的结果只依赖于传入的输入变量和内部逻辑,不依赖于外部,这样的写出的函数没有副作用。举个例子:

public class Person{

 private int a = 1;

 public int add(int b){
  return a + b;
 }

 public int pow(int c){
  return c * c;
 }

 public static void main(String[] args){
  Person p = new Person();
  p.add(1);
  p.pow(2);
 }
}

    上面代码中add(int b)这个方法就不符合函数式编程,这个函数调用后的结果不确定,它的结果不仅取决于b还取决于字段a。而pow(int c)这函数就是符合函数式编程的典范,只要调用它,输入的值c确定了返回值就肯定确定了。
    在函数式编程中,函数也是一等公民,可以被当做参数传递,可以被赋值,被引用,可以把它当做一种数据类型来对待,如果你会使用javascript之类的语言就可以有更深的体会。如果要深入了解这种编程范式可以自行网上搜素资料了解。

1. lambda表达式

    lambda表达式是jdk8中的新特性,上面讲函数式编程就是引入这个,oracle在jdk8中引入了lambda,从此Java中开始对函数式编程的部分支持。
    Java中lambda表达式的语法结构:(params) -> expression。由三部分构成,第一部分是括号以及括号内部的形式参数,第二部分是"->"箭头符号,第三部分是expression方法体,方法体可以是代码块也可以是执行表达式。

//1. lambda表达式的完整形态:有输入参数,有返回值,有代码块。
(int a, int b) -> {
 int c = a + b;
 return c;
}
//2. lambda表达式在某些情况也可以省略一部分
 //2.1 当代码块不需要返回值的 时候可以省略return语句
  (int a, int b) -> {
  int c = a + b;
 }
 //2.2 当代码块只有一句的时候可以省略大括号
  //并且这种情况默认返回这一句代码的执行结果
 (int a, int b) -> a + b; // 同1具有同样的作用
 //2.3 形参的类型可以根据函数式接口的里面的方法声明自行推断
  //可以省略形参类型
 (a, b) -> a + b; // 同1,2.2具有同样的效果
 //2.4 当只有一个参数的时候可以省略,形参的小括号
 a -> a * a;

    接下来展示一个从定义接口到使用lambda表达式的代码

/**
 * description:
 *
 * @author waxxd
 * @version 1.0
 * @date 2019-10-15
 **/
public class Test1 {

 private int a = 1;
 private int b = 2;
 /**
  * 这个方法需要一个IAdd类型的参数
  * @param add
  * @return
  **/
 public int add1(IAdd add){
  return add.add(a,b);
 }
 public static void main(String[] args) {
  Test1 test1 = new Test1();
  // 使用lambda表达式
  int c = test1.add1((a, b) -> a + b);
  System.out.println(c);
  // 使用匿名类
  int d = test1.add1(new IAdd(){
   @Override
   public int add(int a, int b){
    return a + b;
   }
  });
  System.out.println(d);
 }
}

/**
 * description:
 *   函数式接口,里面抽象方法只能有一个
 * @author waxxd
 * @version 1.0
 * @date 2019-10-15
 **/
@FunctionalInterface
public interface IAdd {
 int add(int a, int b);
}

    可以看见使用lambda表达式的方式相对于匿名类代码会精简优雅很多,下面给出一个经常使用的例子,创建线程:

public class Test(){
 public static void main(String[] args) {
  Thread t1 = new Thread(new Runable(){
   System.out.println("使用匿名类的方式创建线程");
  });

  Thread t2 = new Thread( () -> System.out.println("使用lambda方式创建线程"));

  t1.start();
  t2.start();
 
 } 
}

2. 双冒号::符号

    这个符号第一次看见是在c++里面,在c++里面是一个类似标识作用域解析符号或者范围的符号,描述可能不准确,对c++有兴趣的同学可以自行查找。如果了解c++,这个操作符号就勉强类似类似在c++中函数指针,::在Java里面也可以叫做方法引用,就上面说的函数也是一等公民,这里就类似把方法作为参数传入。前面的例子我们使用lambda表达式都类似使用匿名类实现接口的方法,然而还有一种情况我们并不想要自己去实现接口的方法,只是想传进去一个已经有过实现了的方法,就可以使用::,它的语法规则如下:
                  类名::静态方法名 或者 类的实例::实例方法。

List<File> list = new ArrayList<>;
list.forEach(File::getName); // 使用双冒号传递一个函数进来,
list.forEach( file -> file.getName()); // 使用正常的lambda表达式

3. Optional类

    Optional也是jdk8中的一个新的类的,它给予我们更加优雅的方式来处理Java语言中的NPE异常。可以从一定程度上代替if判断, 介绍相关接口:

  • empty 创建一个空的Optional对象
  • of 和ofNullable

of创建一个Optional对象, 如果传入的参数为空则跑出NPE异常.
ofNullable和上面一样, 但是当传入参数为空的时候会调用empty方法创建一个空Optional对象.

Optional<String> of = Optional.of("waxxd");
// 传入空参数会抛出NullPointerException异常
Optional<String> ofNull = Optional.of(null); 
// 以下两句都正常执行
Optional<String> ofNullable = Optional.ofNullable("waxxd");
// 参数为空的时候相当调用Optional.empty()
Optional<String> ofNullableNull = Optional.ofNullable(null); 

get/orElse/orElseGet/orElseThrow

// get 获取Option包裹的值如果值为null则抛出NoSuchElementException异常
String aa = Optional.of("aa").get();
// orElse 获取值如果值为空则返回orElse设置的默认值
String aa1 = Optional.of("aa").orElse("bb");
// orElseGet 获取值如果值为空则内部可以是一个实现Supplier接口的匿名内部类调用提供返回结果
String aa2 = Optional.of("aa").orElseGet( () -> "aaa".toUpperCase());
// orElseThrow获取值如果不存在则抛出后面的异常
Optional.empty().orElseThrow(IllegalArgumentException::new);

// 实际的应用, 也就是上文所说的如何优化if
// 比如你有个接口, 用户传入参数Integer type, 用户也可以选择不传, 不传我们为它设置默认值1
public void f(Integer type){
	if(type = null) {
		type = 1;
	}
	
	Optional.ofNullable(type).orElse(1);
}

到此这篇关于Java8中的lambda表达式、::符号和Optional类的文章就介绍到这了,更多相关Java8 lambda表达式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于SpringAop中JoinPoint对象的使用说明

    基于SpringAop中JoinPoint对象的使用说明

    这篇文章主要介绍了基于SpringAop中JoinPoint对象的使用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • 实体类或对象序列化时,忽略为空属性的操作

    实体类或对象序列化时,忽略为空属性的操作

    这篇文章主要介绍了实体类或对象序列化时,忽略为空属性的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Spring Boot中使用Server-Sent Events (SSE) 实现实时数据推送教程

    Spring Boot中使用Server-Sent Events (SSE) 实

    Server-Sent Events (SSE) 是HTML5引入的一种轻量级的服务器向浏览器客户端单向推送实时数据的技术,本文主要介绍了Spring Boot中使用Server-Sent Events (SSE) 实现实时数据推送教程,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • 谷歌二维码引擎com.google.zxing二维码生成与解析

    谷歌二维码引擎com.google.zxing二维码生成与解析

    这篇文章主要给大家介绍了关于谷歌二维码引擎com.google.zxing二维码生成与解析的相关资料,zxing是google开源的二维码生成和解析工具,需要的朋友可以参考下
    2023-07-07
  • Java中File与byte[]的互转方式

    Java中File与byte[]的互转方式

    这篇文章主要介绍了Java中File与byte[]的互转方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • Java I/O深入学习之File和RandomAccessFile

    Java I/O深入学习之File和RandomAccessFile

    这篇文章主要介绍了Java I/O深入学习之File和RandomAccessFile, I/O系统即输入/输出系统,对于一门程序语言来说,创建一个好的输入/输出系统并非易事。在充分理解Java I/O系统以便正确地运用之前,我们需要学习相当数量的类。,需要的朋友可以参考下
    2019-06-06
  • java留言管理系统中模糊查询实例分享

    java留言管理系统中模糊查询实例分享

    这篇文章主要为大家详细介绍了基于MVC+DAO的留言管理系统中java模糊查询的简单使用方法,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • Java元注解meta-annotation和依赖注入详解

    Java元注解meta-annotation和依赖注入详解

    这篇文章主要给大家介绍了关于Java元注解meta-annotation和依赖注入的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • SSH框架网上商城项目第18战之过滤器实现购物登录功能的判断

    SSH框架网上商城项目第18战之过滤器实现购物登录功能的判断

    这篇文章主要为大家详细介绍了SSH框架网上商城项目第18战:过滤器实现购物登录功能的判断,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • java 获取日期的几天前,几个月前和几年前的实例

    java 获取日期的几天前,几个月前和几年前的实例

    下面小编就为大家带来一篇java 获取日期的几天前,几个月前和几年前的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10

最新评论