Lambda表达式是JDK8的一个新特性,可以取代大部分的匿名内部类,写出更优雅的Java代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。
JDK也提供了大量的内置函数式接口供我们使用,使得Lambda表达式的运用更加方便、高效。
Lambda表达式,也称为闭包:java8的新特性,lambda运行将函数作为一个方法的参数,也就是将函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁。
Lambda表达式常用于简化接口实现,关于接口实现,可以有很多种方式。例如:创建接口的实现类;或者使用匿名内部类;
举例说明:
接口和继承实现
public interface TestInterface {
public void test();
}
public class TestInterfaceImpl implements TestInterface {
@Override
public void test() {
System.out.println("实现继承接口方法");
}
}
使用
@Test
public void t7(){
//继承实现接口
System.out.println("继承实现接口==============");
TestInterface service=new TestInterfaceImpl();
service.test();
System.out.println("匿名类实现接口==============");
service=new TestInterface(){
@Override
public void test() {
System.out.println("匿名类实现");
}
};
service.test();
System.out.println("匿名类调用==============");
new TestInterface(){
@Override
public void test() {
System.out.println("匿名类调用直接调用");
}
}.test();
}
使用lambda表达式就非常简单:
TestInterface ts=()->{
System.out.println("我用使用lambda语法来实现接口");
};
ts.test();
基本语法: (parameters) ->{ statements; }
(parameters)就是省略了类名的构造函数
->是lambda标志,后面是方法体{}
new Class类名《省略类名》(构造参数) ->{
函数语句
}
Lambda表达式由三部分组成:
// 1. 不需要参数,返回值为 2
() -> 2
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的和
(x, y) -> x + y
// 4. 接收2个int型整数,返回他们的乘积
(int x, int y) -> x * y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
要了解Lambda表达式,首先需要了解什么是函数式接口,函数式接口定义:一个接口有且只有一个抽象方法
注意:
1.如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
2.如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。
定义方式:
@FunctionalInterface
public interface NoParameterNoReturn {
void test();
}
函数接口声明,声明无返回函数接口
//1.无参无返回函数接口
@FunctionalInterface
public interface NoParameterNoReturn {
void test();
}
//2.有参无返回参数
public interface OneParameterNoReturn {
public void test(int x);
}
//3.多参无返回函数接口
@FunctionalInterface
public interface NoParameterNoReturn {
void test();
}
lambda和匿名实现类的对比
@Test
public void t0() {
NoParameterNoReturn n = () -> {
System.out.println("无参无返回参数");
};
n.test();
//lambda表达式等价于匿名类接口实现
NoParameterNoReturn nn=new NoParameterNoReturn(){
@Override
public void test() {
System.out.println("无参无返回参数");
}
};
nn.test();
System.out.println("==========================================");
OneParameterNoReturn o=(x)->{
System.out.println("x的值==="+x);
};
o.test(200);
//lambda表达式等价于匿名类接口实现
OneParameterNoReturn on=new OneParameterNoReturn(){
@Override
public void test(int x) {
System.out.println("x的值==="+x);
}
};
on.test(200);
}
有返回值的接口函数
//1.无参有返回函数接口
public interface NoParamReturn {
public int test();
}
//2.有参有返回函数接口
public interface OneParamReturn {
public int test(int x);
}
//3.多参有返回函数接口
public interface MoreParamReturn {
public int test(int x,int y);
}
对应的lambda函数
@Test
public void t2(){
NoParamReturn nr=()->{
return 666;
};
System.out.println(" nr.test()="+ nr.test());;
NoParamReturn nr2=()->2;
System.out.println(" nr2.test()="+ nr2.test());;
OneParamReturn or=(x)->{
return 2*x;
};
System.out.println(" or.test(100)="+ or.test(100));
MoreParamReturn mr=(x,y)->{
return x+y;
};
System.out.println("mr.test(100, 300)="+mr.test(100, 300));
}
1.参数类型可以省略,如果需要省略,每个参数的类型都要省略。
A a=(int x,int y)->{return 2;};
可以简写成
A a=(x,y)->{return 2;};
2.参数的小括号里面只有一个参数,那么小括号可以省略
A a=(int x)->{return 2;};
可以简写
A a=x->{return 2;}; //这种说实话,不好理解
3.如果方法体当中只有一句代码,那么大括号可以省略
A a=x->System.out.println(“ffff”);
4.如果方法体中只有一条语句,其是return语句,那么大括号可以省略,且去掉return关键字
()->2;
(x)-> 2x;
x-> 2;
再看示例:
public static void main(String[] args) {
MoreParameterNoReturn moreParameterNoReturn = (a, b)->{
System.out.println("无返回值多个参数,省略参数类型:"+a+" "+b);
};
moreParameterNoReturn.test(20,30);
OneParameterNoReturn oneParameterNoReturn = a ->{
System.out.println("无参数一个返回值,小括号可以省略:"+ a);
};
oneParameterNoReturn.test(10);
NoParameterNoReturn noParameterNoReturn = ()->System.out.println("无参数无返回值,方法体中只有 一行代码");
noParameterNoReturn.test();
//方法体中只有一条语句,且是return语句
NoParameterReturn noParameterReturn = ()-> 40;
int ret = noParameterReturn.test();
System.out.println(ret);
}