Java8 (一) lambda表达式 和 函数式接口

前言:

目前接触的项目中大量使用Java8的语法、看起来代码十分的简洁、优雅、可能一开始 阅读起来 有些不习惯、但是看的多了以及自己最近自己在写项目的时候用的 多了, 感觉Java8 的这些新的语法是使得目前 java可以 继续活跃在原因之一。

PS:(由于最近一两个月在做项目已经学习一些新知识,导致最近没怎么写blog、最近就开始总结这一两个月学到用到的知识、做个归纳总结)

一、Java8和之前版本简单比较

个人理解: lambda表达式的出现可以替换之前没有函数式接口以及lambda表达式之前的 要实现一个匿名函数的过程、使得代码变得简洁。
举个常用的例子: 创建一个线程 并实现 runnable接口
在这里插入图片描述
之前在java8 没有出现的时候 程序内部会有很多种这种内部匿名类、匿名函数之类的、并且代码显得臃肿、上述几行代码中、最终要做的事 其实就一行 System.out.println(“hello”); 其他代码就显得很冗余,因此java8就使用lambda表达式以及函数式接口用于简化上述过程(和json格式替换xml格式的用于存储数据的思想很像)。

使用lambda表达式实现上述内容如下:
在这里插入图片描述
可以看到相比之前的实现方式,代码显得很简洁优雅。

二、lambda表达式语法格式

2.1 书写格式

lambda表达式由三部分组成:入参 、 ->、方法体
格式: (参数列表) -> {一些重要方法的代码}

   eg: Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );
2.1.1 参数列表

在入参部分 可以不用指定参数类型、 编译器会根据上下文推导出 参数的类型

其中参数列表部分 使用() 包裹起来、 如果没有输入参数的话,则不用输入、

1、无输入参数

eg: Thread thread1 = new Thread(() -> {System.out.println("helllo");});

2、一个或多个输入参数
其中单个输入参数可以用 ()包裹, 要是多个输入参数的话 需要使用()包裹

// 一个参数:
Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );

// 多个入参:
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
2.2 方法体

1、若方法体中只有一行语句块,则可以不用{}包裹、若有多个语句块、则需要包裹起来 作为匿名函数的 具体实现方法体。
2、方法体中的返回值 由lambda表达式 对应的 函数接口中的 抽象方法决定,可以有返回值、也可以没有返回值、其中若是 单个与具体中的 return 可以省略不写。

详细内容在介绍完 函数式接口后一起介绍

三、函数式接口

函数式接口是Java8引入得到一个设计、其主要就是用于适配lambda表达式。

3.1 定义

函数式接口一般指的就是一个抽象接口并且其中 只有一个抽象方法,(Java8 为了兼容之前的版本,新引入了 default 字段, 被default修饰的方法 标识该方法可以在 接口中实现、而该接口对应的实现类 可以不实现该 default修饰的 方法、 若是 字类 又重写了该方法、则最终调用的是字类实现的 方法中的内容)
其中函数式接口通过注解 @FunctionalInterface 修饰、添加了该注解后、编译器会自动对其检查 保证该接口必须有且只有一个抽象方法:

eg:

package org.lm;

@FunctionalInterface
public interface FunctionalTest {
    void method();
}

ps: 静态方法 和 被default修饰的方法 不会破坏函数式接口的定义

package org.lm;

@FunctionalInterface
public interface FunctionalTest {
    void method();

    default void defaultMethod(){
        System.out.println("default method");
    }

    static void staticMethod() {
        System.out.println("static method");
    }
}

使用自定义函数式接口与lambda表达式 融合测试:
自定义函数式接口 FunctionalTest 并且 定义了一个抽象方法 method()
在这里插入图片描述
使用lambda表达式 测试 自定义的函数式接口
在这里插入图片描述

执行结果:
在这里插入图片描述

3.2 四种抽象的 函数式接口

Java8 为我们创建提供好了提前定义好的函数式接口,其位置在 java.util.function

四种类型的抽象的函数式接口 分为 一元、 二元的。 其中二元的函数式接口一般 定义 以 ***Bixxxx ***开头 (Binary )

3.2.1 消费者 型函数式接口 – Consumer

此类型函数接口 无返回值、消费 输入的参数

一元类型***的消费者形函数式接口 Consumer*** 其抽象方法为 accept

	// 需要显示调用accept方法  才会执行lambda表达式中的方法体里的内容
	Consumer<String> consumer = (x) -> System.out.println("consumer: " + x);
	consumer.accept("Hello");

在这里插入图片描述

二元类型 消费者函数式接口
在这里插入图片描述

3.2.2 供给 型函数式接口 – Supplier

无输入参数,返回T类型的一个结果。

一元类型的 供给型函数接口 抽象方法 :get

	Supplier<String> supplier = () -> "Test supplier";
	supplier.get();

在这里插入图片描述
无二元类型的 供给函数接口(函数只能返回一个值 不可能返回两个值)

3.2.3 谓词型函数式接口 – Predicate

接受一个T类型的参数,返回布尔值

一元类型的定义:
在这里插入图片描述

二元类型定义:
在这里插入图片描述

3.2.4 Function

接受一个T类型的参数,返回R类型结果。

一元定义:
在这里插入图片描述

二元定义:
在这里插入图片描述

四、关于lambda表达式 使用外部变量

上周在做项目的时候: 在lambda表达式外部定义了一个 Boolean类型的 局部变量、 在 lambda表达式内部对其进行修改时 发现编译器提示这种是非法的,
报错:
Variable used in lambda expression should be final or effectively final

原因大概有两点:
1、变量必须是final类型的
2、如果没有定义成final,那么变量在初始化以后,不允许再有任何赋值的情况出现。(其实就是隐式final限制

一般解决:
可以用集合、数组、对象等 引用传递的方式 将局部参数传递进 lambda表达式内部 进行修改。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值