Java-Lambda表达式

在Lambda出现之前的函数编程中,通过单个接口表示类型,实例作为函数对象,表示函数或者要采取的动作。而使用函数对象的方式往往是通过声明匿名类,示例如下

Thread thread = new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("匿名类");
	}
});

上面的代码中,实际传递功能的只有System.out.println(“匿名类”)这一段代码。可以看出,在Java中传递一个代码段并不容易,不能直接传递代码段,因为Java是一种面向对象语言,所以必须构造一个对象,这个对象的类需要有一个方法能包含所需的代码。这种方式是非常繁琐的,为了一行功能代码需要编写很多通用的代码行。
在Java8中,出现了Lambda表达式,将定义了执行过程的匿名内部类的创建过程进行了简化。

相关概念

函数接口

在Java8中,带有单个抽象方法的接口是特殊的,它们被称为函数接口。对于函数接口,可以有默认方法和static方法,但是抽象方法只能有一个。

Lambda表达式

Java8以后允许用Lambda表达式来表示函数接口,它是对匿名类表示的函数的简化。
lambda 表达式是一个特定规则的可传递的代码块,可以在以后调用中执行一次或多次;它代表的是一种行为,并不是执行的结果。

匿名类和Lambda表达式的区别
  • 匿名类中的this指的是类本身,在Lambda中this指的是它的调用类
  • 匿名类可以屏蔽包含类的变量,Lambda表达式不能
  • 匿名类的类型是在初始化时确定的,Lambda表达式的类型取决于它的上下文

Lambda表达式结构

Lambda的基本语法是(parameters) -> expression或(请注意语句的花括号)(parameters) -> { statements; }
即:参数,箭头(->) 以及一个表达式。

  • 参数
  • 代码块
  • 自由变量的值。这是指非参数而且不在代码中定义的变量。这个值在初始化之后就不能被改变,必须为final的,从函数角度来说,对于同一个函数,多次传入相同的参数,那么获取的结果应该是一致的,因此对于函数中的自由变量,应该是不变的。这里假设一个数学函数 2x + 1,x为参数,2为自由变量,那么这个2应该是一致不变化的。
示例
Function<Integer, String> f = (Integer a) -> a.toString();
  • 即使lambda 表达式没有参数, 仍然要提供空括号,就像无参数方法一样
Runnable run = ()->System.out.println("执行");
  • 如果可以推导出一个lambda 表达式的参数类型,则可以忽略其类型。对于需要参数的函数,一般情况下不需要指定参数类型,虚拟机会根据上下文进行类型推导,如果编译期报错,则必须加上参数类型。
Function<Integer, String> f = a -> a.toString();

在这里插入图片描述

::的使用

参考方法引用部分

Lambda使用场景

  • 使用匿名函数的地方大多都可以用Lambda表达式替代,且优先于使用匿名函数。
  • 反复调用函数表达式,或者延迟调用
不能用表达式取代匿名类的场景
  • 创建抽象类的实例
  • 为多个抽象方法的接口创建实例
  • 需要在匿名方法中引用this实例的情景,lambda表达式中this实例是对外部的引用。

Java自带函数接口使用

使用方式以Function举例:结合default方法

  • Function<T, R>
Function<String, Integer> f = x -> Integer.valueOf(x);
Function<String, String> s = y -> y + "1";
Function<String, Integer> d = f.compose(s);
System.out.println(d.apply("123"));
Function<String, String> a = x -> {
	System.out.println("a输出" + x);
	return x + "0";
};
Function<String, String> b = x -> {
	System.out.println("b输出" + x);
	return x + "1";
};
Function<String, String> c = x-> {
	System.out.println("c输出" + x);
	return x + "2";
};
a = a.compose(b);
a = a.andThen(c);
System.out.println("输出" + a.apply("abc"));

Java自带函数接口

在这里插入图片描述
在这里插入图片描述

其他

  1. lambda 表达式中捕获的变量必须实际上是最终变量(effectivelyfinal。)实际上的最终变量是指,这个变量初始化之后就不会再为它赋新值。
  2. 函数式接口最好带有@FunctionalInterface的标注
@FunctionalInterface
public interface Function<T, R> {
...
}
  1. 序列化问题-参考 Lambda表达式的序列化
  2. 如果Lambda表达式抛出一个异常,那么抽象方法所声明的throws语句也必须与之匹配
  3. 为了避免使用泛型带来的装箱操作,因此增加了相关的接口,如:IntPredicate等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值