在《java8实战》这本书中,对Lambda的解释如下:
可以把Lambda表达式理解为简洁的表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表,函数主体,返回类型,可能还有一个可以抛出的异常列表。
简述
1. Lambda表达式的类比
1.lambda表达式是从匿名内部类演化过去的,是匿名内部类的简化版本
public static void test01() throws IOException {
// lambda表达式是从匿名内部类演化过去的,是匿名内部类的简化版本
Runnable r1 = new Runnable() {
public void run() {
System.out.println("not lambda");
}
};
r1.run();
Runnable lambda01 = () -> {
System.out.println("lambda01");
};
lambda01.run();
UnblockedCallback lambda02 = () -> System.out.println("lambda02");
lambda02.handle();
}
2. Lambda表达式的标准格式和省略模式以及注意事项
Lambda表达式的标准格式
1,格式:(形式参数)->{代码块}。
2,形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空就可以了。
3,->:固定写法,代表指向动作。
4,代码块:就是你想干的事。
3. Lambda表达式的省略模式
省略规则:
1,参数类型可以省略,但在多参数的时候,不能只省略一个参数的类型(就是要么全部省略,要么都不省略)。
2,如果参数只有一个,小括号可以省略。
3,如果代码块只有一条,可以省略大括号和分号,以及return关键字。
相关知识 泛型
4. Lambda表达式的注意事项
注意事项:
1,使用Lambda表达式必须要有接口,并且要求接口中有且仅有一条抽象方法。此类接口称为"函数式接口"。
2,必须要有上下文环境,才能导出Lambda对应的接口
(1),根据局部变量得知Lambda对应的接口:Runnable r = () -> System.out.println();
(2),根据调用方法的参数得知Lambda对应的接口:new Thread(() -> System.out.println()).start()。
5. Lambda表达式的 “::” 双冒号符注意事项
这个“::”到底是什么语法呢?
在JAVA 8 中,可以通过 “::” 关键字来访问类的构造方法,对象方法,静态方法。一般有下面几种用法。
访问静态方法 // 使用方法:类名::静态方法名, 如 Integer::parseInt
访问对象方法 // 使用方法:实例对象::实例方法,如 String::substring
访问构造方法 // 使用方法:类名::new, 如 User::new
example
// supplier
public static void test07() {
/**
* 创建对象的工厂
* 每次调用get()方法时都会调用构造方法创建一个新对象。 理解:将创建对象的方式封装,使得对象的创建更加优美
*/
Supplier<String> supplier = String::new;
System.out.println(supplier.get());//""
Supplier<Emp> supplierEmp = Emp::new;
Emp emp = supplierEmp.get();
emp.setName("dd");
System.out.println(emp.getName());//dd
}
6. 一元,二元,三元操作符
“元”就是参与运算的操作数
一元运算
++,–,!,正数符号,负数符号……
二元运算 +,-,*,/,%……
三元运算只有一个
(布尔表达式)? 表达式1:表达式2;
如果满足布尔表达式,表达式1就是三元运算的值
不满足布尔表达式,表达式2就是三元运算的值
7.流式操作核心思想
流式编程即链式编程终端操作与中间操作为其过程中的操作,
中间过程类似加入的感觉加入后返回一个同样类型的对象然后具有上一个操作对象的函数,
终端操作返回的则是不同于上一个操作类型的对象。
8. lambda表达式基础语法
java中,引入了一个新的操作符“->”,该操作符在很多资料中,称为箭头操作符,或者lambda操作符;箭头操作符将lambda分成了两个部分:
- 左侧:lambda表达式的参数列表
- 右侧:lambda表达式中所需要执行的功能,即lambda函数体
- lambda表达式语法格式;
1).无参数,无返回值的用法 :() -> System.out.println(“hello lambda”);
@Test
public void test1() {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("hello runnable");
}
};
r.run();
Runnable r1 = () -> System.out.println("hello lambda");
r1.run();
}
2). 有一个参数,无返回值的用法: (x) -> System.out.println(x); 或者 x -> System.out.println(x); 一个参数,可以省略参数的小括号
@Test
public void test2(){
Consumer<String> con = (x) -> System.out.println(x);
con.accept("有一个参数,无返回值的用法(Consumer函数式接口)");
}
3).有两个参数,有返回值的:(x, y) -> x + y
public void test3() {
BinaryOperator<Integer> binary = (x, y) -> x + y;
System.out.println(binary.apply(1, 2));// 3
}
4).剩下的多个参数,就不在继续介绍了,按照上面的推测,就可以了,上面的例子,函数体中,都是一行语句,最后一个语法,介绍下,lambda表达式中,多行语句,分别在无返回值和有返回值的抽象类中的用法
@Test
public void test4() {
// 无返回值lambda函数体中用法
Runnable r1 = () -> {
System.out.println("hello lambda1");
System.out.println("hello lambda2");
System.out.println("hello lambda3");
};
r1.run();
// 有返回值lambda函数体中用法
BinaryOperator<Integer> binary = (x, y) -> {
int a = x * 2;
int b = y + 2;
return a + b;
};
System.out.println(binary.apply(1, 2));// 6
}
可以看到,多行的,只需要用大括号{}把语句包含起来就可以了;有返回值和无返回值的,只有一个return的区别;只有一条语句的,大括号和renturn都可以不用写;
5).lambda的类型推断
@Test
public void test5() {
BinaryOperator<Integer> binary = (Integer x, Integer y) -> x + y;
System.out.println(binary.apply(1, 2));// 3
}
可以看到,在lambda中的参数列表,可以不用写参数的类型,跟java7中 new ArrayList<>(); 不需要指定泛型类型,这样的<>棱形操作符一样,根据上下文做类型的推断
lamabd表达式中,需要有函数式接口的支持;
函数式接口定义:接口中只有一个抽象方法的接口,称为函数式接口;
可以使用@FunctionalInterface注解修饰,对该接口做检查;如果接口里,有多个抽象方法,使用该注解,会有语法错误