java实现⼆元函数运算_Java函数式编程-2.Lambda表达式1.什么是lambda表达式?
⾸先看⼀段⽐较熟悉的代码⽚段,⽬的是为按钮注册⼀个事件,当按钮被点击时输出⼀个提⽰信息"button clicked",
Button button = new Button();
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("button clicked");
}
});
这段本⾝没有什么问题,但是代码量相对有点多⽽且语义表达上也不够清新。那么什么样的表达才是清晰的呢?Jdk8给我带来了⼀种全新的思路,可以让我们更加优雅的实现上述功能,我们看下述Lambda
代码。
Button button = new Button();
button.addActionListener(e-> System.out.println("button clicked"));
2.lambda 表达式3种表现形式
⽆参数表达式: () -> System.out.println(“hello world!”)
单个参数表达式 :  (String  sayHello) -> System.out.println(sayHello)
多个参数表达式:  (int x, int y) -> x + y
需要注意的是以上三种基本形式可以根据“是否有显⽰声明参数类型”、“是否有返回值”、“是否省略()”等⼜会衍⽣出若⼲变化。
3.lambda表达式值引⽤
lambda表达式操作的是对象的引⽤值⽽不是对象本⾝,怎么理解呢?匿名内部类如果引⽤所在⽅法中变量那么该变量必须声明为final类型,也就是对象只能对赋值⼀次。类似的lambda表达式引⽤所在⽅
法中的变量也必须是final类型,表现形式上可以显⽰声明final 也可以不显⽰声明,但是该变量必须是⼀个既成事实上的final变量。
public static void sayHello(String name) {
if (Objects.isNull(name)) {
name = "kity";
}
ActionListener act = event -> System.out.println("hello " + name);
....
}
上述代码变异会提⽰ Variable used in lambda expression should be final or effectively final。
4.lambda表达式⽅法引⽤
以前我们关注更多的是对象引⽤,jdk8之后新增了⽅法引⽤,需要使⽤关键字 “::”,这是jdk8我们需要重点关注的。⼀下我们详细列举6种⽅法引⽤的详细格式。
静态⽅法引⽤
格式  类名::静态⽅法名
注意事项:
被引⽤⽅法参数列表和函数式接⼝中⽅法的参数⼀致
接⼝的抽象⽅法没有返回值,引⽤的⽅法可以有返回值也可以没有接⼝的抽象⽅法有返回值,引⽤⽅法必须有同类型的返回值interface Transfer {
int run(String string);
}
public static void main(String[] args) {
printStr("1", Integer::valueOf);
}
public static void printStr(String str, Transfer t) {
int num = t.run(str);
System.out.println(num);
}
对象⽅法引⽤
格式  对象::⽅法名
@FunctionalInterface
interface Action {
String run(Integer num);
}
public static void main(String[] args) {
Action t2 = new Person()::walking;
System.out.println(t2.run(5));
}
class Person {
public String walking(Integer num) {
return "go ".concat(String.valueOf(num)).concat(" step ..."); }
}
构造⽅法引⽤
格式  类名::new
interface Action {
Person init(String string);
}
class Person {
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
public static void main(String[] args) {
Action t2 = Person::new;
Person p2 = t2.init("李四");
System.out.println(p2);
}
数组构造⽅法引⽤
格式  数据类型[]::new
interface Action {
String[] run(int len);
}
public static void main(String[] args) {
Action action = String[]::new;
String[] arr = action.run(5);
System.out.println(arr.length);
}
特定类型的⽅法引⽤
格式  类名::⾮静态⽅法
ArrayList list = new ArrayList<>();
Collections.addAll(list, "a", "C", "B", "d"); Collections.sort(list, String::compareToIgnoreCase); System.out.println(list);
类中⽅法调⽤⽗类或本类⽅法引⽤
格式  this::⽅法名
super::⽅法名
interface Action {
void init();
}
class Father {
public void buy() {
System.out.println("买东西");
}
}
class Son extends Father {
public void buy() {
System.out.println("买糖");
}
public void run() {
Action action1 = this::buy;
action1.init();
Action action2 = super::buy;
action2.init();
}
}
public static void main(String[] args) {
Son s = new Son();
s.run();
}
5.lambda函数接⼝
函数式接⼝是 Java8 引⼊的⼀个新特性,是⼀种特殊的接⼝:SAM类型的接⼝(Single Abstract Method),但本质上还是接⼝。相⽐较于其他接⼝,函数式接⼝有且只能有⼀个抽象⽅法。只要接⼝中出现多个抽象⽅法,那么就不能称之为函数式接⼝,运⾏的时候就会报错。为此 Java8 提供了⼀个新的注解@FunctionalInterface,如果接⼝被这个注解标注,就说明该接⼝是函数式接⼝,如果有多于⼀个的抽象⽅法,在编译的时候就会报错。但是这个注解不是必需的,只要接⼝符合函数式接⼝的定义,那么这个接⼝就是函数式接。
Java中主要的函数接⼝
接⼝
参数
返回类型
描述
Predicate
T
boolean
断⾔型接⼝
Consumer
T
void
消费型接⼝
Function
T
R
功能型接⼝
Supplier
None
T
供给型接⼝
UnaryOperator
T
T
⼀元运算
BinaryOperator
(T,T)
T
⼆元运算lambda编程
6.lambda函数类型推断
Lamda表达式是函数式接⼝的⼀个实例,然⽽我们并没有从Lambda表达式中看到有关函数式接⼝的任何信息,因⽽有必要弄清楚Lambda 的类型是什么?它实现了哪个函数式接⼝?其实Lambda表达式的类型是从上下⽂推断出来的,这⾥的上下⽂包括如下3种:
赋值上下⽂
⽅法调⽤上下⽂(参数与返回值)
类型转换上下⽂
通过这3种上下⽂就可以推断出Lambda表达式的⽬标类型(与之对应的函数式接⼝)。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。