详解Java8中的lambda表达式、::符号和Optional类
作者:WAXXD 发布时间:2022-02-03 03:04:56
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);
}
来源:https://blog.csdn.net/WAXXD/article/details/115329438


猜你喜欢
- 前言:随着用户体验的不断的加深,良好的UI视觉效果也必不可少,以前方方正正的对话框样式在APP已不复存在,取而代之的是带有圆角效果的Dial
- public static string encode(string str) { &
- 反射允许我们在编译期或运行时获取程序集的元数据,通过反射可以做到:● 创建类型的实例● 触发方法● 获取属性、字段信息● 延迟绑定.....
- 请求SpringBoot接受前台参数的六种方式,首先因为从前台发送的请求没有界面的话只能是从地址栏发送并且只能是Get请求,为了测试其他的请
- Java继承方法重写是Java语言多态的特性,必须满足以下条件在子类中,方法名称与父类方法名称完全相同方法的参数个数和类型完全相同,返回类型
- java 读取本地文件实例详解用javax.xml、w3c解析实例代码:package cn.com.xinli.monitor.utils
- Flutter 是 Google 开源的 UI 工具包,帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web、桌面和嵌入式平台。
- 一、项目前提1、购物车并不是一直放数据库2、选择使用的技术:session:(购物车项目使用session)好处:快(放在内存当中),存对象
- 前言:图片选择器基本上是每个App必备的东西,用公认好的第三方也可以,但是自己写的改起来方便,用起来顺手,而且这东西想想可能没动手之前想想比
- 这篇文章主要介绍了springmvc处理模型数据ModelAndView过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一
- 前言对于数组遍历,基本上每个开发者都写过,遍历本身没什么好说的,但是当我们在遍历的过程中,有一些复杂的业务逻辑时,将会发现代码的层级会逐渐加
- Android中图片的左右切换随处可见,今天我也试着查阅资料试着做了一下,挺简单的一个小Demo,却也发现了一些问题,话不多说,上代码~:使
- 一、简介在现阶段的Android开发中,注解越来越流行起来,比如ButterKnife,Retrofit,Dragger,EventBus等
- 引言在性能测试过程中,验证HTTP code和响应业务code码是比较基础的,但是在一些业务中,这些参数并不能保证接口正常响应了,很可能返回
- AOP注解无效,切面不执行的解决想做一个api请求日志,想到使用aop,配置过程中遇到了一个坑,aop不起作用,我的aop是这样的:pack
- 起因:有后端同事反馈在异步线程中获取了request中的参数,然后下一个请求是get请求的话,发现会偶尔出现参数丢失的问题.示例代码:@Ge
- Main方法如下:static void Main(string[] args){ dynamic st
- 本文实例讲述了C#数据结构之双向链表(DbLinkList)。分享给大家供大家参考,具体如下:这是继上一篇《C#数据结构之单链表(LinkL
- 一、引言以前在饿了么上面订餐的时候,曾经看到过这么一个特效,就是将商品加入订单时,会有一个小球呈抛物线状落入购物车中,然后购物车中的数量会改
- 1.在action中定义变量 private List<String> downLoadPaths = new ArrayLis