- 以逗号隔开的参数列表(xx,xx,xx…)
- ->符号
- Lambda表达式方法体。(λ代码块)
1.删减了大量的无用代码,使得编程可以直奔核心;
2.让Java开始支持函数式编程。
现在,先用传统方式,实现一个入门级的多线程程序,如下。
//以多线程为例。我们要启动一个多线程需要
@Test
void contextLoads() {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程执行");
}
}).start();
}
程序中,new Thread()的参数是一个Runnable 接口,本次用匿名内部类方式实现了该接口,并重写了接口中的run()方法。但仔细读这种代码,容易发现 里面出现了大量的无用代码
代码中方法必不可少的东西:
(1)run()方法的参数列表:()
(2)方法体:System.out.print(…)
其中很容易理解,对于一个方法(函数)而言,参数列表和方法体 是没法省略的。(有人可能问:为什么返回值类型可以省?因为lambda有自动类型推测机制,可以根据return值 自动推算出返回值类型)。
好,搞懂以上后,lambda表达式的语法就出来了:
lambda表达式由 参数列表 和方法体 两部分组成,并且二者之间使用“->”进行连接。lambda表达式的最大作用,就是对上述形式的“匿名内部类”进行简化。现在,将上述代码,使用lambda写成如下的等价程序。
@Test
void contextLoads() {
new Thread( () ->{
System.out.println("线程执行");
}
}).start();
}
将原来那些冗余的代码去掉以后,我们的代码变得简洁了很多
2.2 、让Java开始支持函数式编程。再仔细观察这句代码:
new Thread( () ->{
System.out.println("线程执行");
}
}).start();
在使用lambda时,我们可以将 一段“函数”传到一个方法中,本次是将“() ->System.out.println(“Hello World”)”这段函数 作为参数,传到了new Thread(…)的构造方法中了。大家回忆一下,在以前,方法的参数是不是只能是 变量或表达式?因此lambda的出现,就可以让函数传到了方法的参数中,这也称为函数式编程。
3.函数式接口 3.1、函数式接口的定义函数式接口是指被@FunctionalInterface注解修饰,且有且只有一个抽象方法的接口。这是因为假如接口有多个抽象方法,使用lambda表达式表达的就不知道是哪个方法了。
@Test
void contextLoads() {
new Thread( () ->{
System.out.println("线程执行");
}
}).start();
}
//创建Thread对象时,需要传入一个Runnable对象,假如Runnable有多个抽象方法。lambda表达式就不知道重写哪个方法了
注意:lambda表达式重写的必须是函数式接口(或者只有一个抽象方法的抽象类)
函数式接口需要注意以下几点:
- 即使没有标注@FunctionalInterface ,但是只有一个抽象方法,也称之为函数式接口。
- 特殊情况:如果某个接口中有多个抽象方法,但是只有一个抽象方法是本接口新定义的,其他抽象方法和Object中已有的方法重复,那么该接口仍然是函数式接口。(这种情况比较极端,了解即可)
存放位置:函数式接口大部分放在java.util.function包下
jdk自带了4大函数式接口:
//四大核心函数式接口 //有参,无返回值(消费型) @FunctionalInterface public interface Consumer4、Lambda表达式的用法 4.1、第一种用法:定义一个函数式接口,用Lambda重写抽象方法{ void accept(T t); } //无参,有返回值(供给型) public interface Supplier { T get(); } //有参,有返回值(函数型) @FunctionalInterface public interface Function { R apply(T t); } //断言式接口 @FunctionalInterface public interface Predicate { boolean test(T t); }
基本语法:函数式接口 变量名= lambda表达式。
上示例
@Test
public void testLambda() {
//1. 测试使用断言型接口
Predicate isGood = (sorce) -> {//la
return sorce > 80;
};
//上面这一步就相当于我们重写了Predicate接口的test(T t)方法
System.out.println("Predicate接口断言你成绩及格时间为"+isGood.test(100));
isGood.test(100);//调用重写后的test方法
//2. 测试使用函数型接口
Function function=(a)->{
return "Function接口接收参数"+a+",并将它进行二次方计算返回"+a*a;
};
//使用lambda表达式重写Function接口的R apply(T t)方法
System.out.println(function.apply(100));//调用重写后的apply方法
//3. 测试使用消费型接口
Consumer consumer=(a)-> {System.out.println("Consumer接口消费了:"+a);};
consumer.accept("苹果");
// 4. 测试使用生产型接口
Supplier supplier=()->{
return "Supplier生产粮食";
};
System.out.println(supplier.get());
}
4.2、第二种用法:将Lambda表达式代表的函数式接口作为一个方法的参数存在。


