Lambda
Lambda表达式是JDK1.8引入的特性,它是一个优雅的语法,使得代码更加简洁明了。
引言
设此时存在一个接口Interface01,如果想要调用其中的show()方法,我们需要怎么做?
-
方法一:使用实现类
我们创建一个对应的实现类并编写具体的实现方法
public class Interface01Impl implements Interface01{ @Override public void show() { System.out.println("使用实现类实现"); } public static void main(String[] args) { Interface01 interface01 = new Interface01Impl(); interface01.show(); } }
-
方法二:使用匿名内部类
public static void main(String[] args) { Interface01 interface01 = new Interface01() { @Override public void show() { System.out.println("使用匿名内部类实现"); } }; interface01.show(); }
这样的形式已经很简便了,不需要创建实现类。还有更进一步的方式吗?
-
方式三:使用Lambda表达式
public static void main(String[] args){ Interface01 interface01 = () -> { System.out.println("使用Lambda表达式"); }; interface01.show(); }
这样猛的一看,似乎没有特别简便呀,那如果是这样写呢
public static void main(String[] args){ ((Interface01) () -> System.out.println("使用Lambda表达式")).show(); }
在这里,我们只需要一行代码,就可以实现简单的接口逻辑
Lambda表达式
当存在一个接口,且接口内仅存在一个抽象方法时,可以使用Lambda表达式。
格式:(形式参数) -> {代码块}
这样看格式肯定有点懵的,我们从匿名内部类开始分析,逐步过渡到Lambda表达式。
先来看下匿名内部类的写法
Interface01 interface01 = new Interface01() {
@Override
public void show() {
System.out.println("啦啦啦");
}
};
interface01.show();
-
在匿名内部类的写法中,我们知道new的一定是个接口,所以需要省略接口名和大括号
-
因为接口内部只有一个抽象方法,所以需要省略抽象方法的名称、修饰符、返回值
-
结合Lambda的格式
(形式参数) -> {代码块}
,在参数的小括号和代码块的大括号中间加 -> 符号Interface interface01 = ()->{System.out.println("啦啦啦")}
至此,我们写好了一个标准的Lambda表达式。
Lambda表达式的省略形式
上面书写的都是无参的情况。如果有参数,有返回值的是什么样呢
设存在一个接口Interface02
public interface Interface02 {
int add(int a, int b);
}
我们书写它的Lambda表达式来实现add方法
Interface02 interface02 = (int a,int b) -> {
return a+b;
};
interface02.add(1,2);
-
参数类型可以省略,但不能只省略一部分【如改为(int a,b)】
Interface02 interface02 = (a, b) -> { return a+b; }; interface02.add(1,2);
-
如果代码块语句只有一行,可以省略大括号和分号。
如果这一行包括return,return也要省略
Interface02 interface02 = (a, b) -> a+b; interface02.add(1,2);
-
如果参数只有一个,可以省略参数的小括号
修改前
Interface03 in03 = (a) -> System.out.println(a);
修改后
Interface03 in03 = a -> System.out.println(a);
Lambda还真是…简略的不能再简略了…
注意事项
-
使用Lambda的前提条件是,必须为接口且仅有一个抽象方法。
-
使用Lambda必须要有上下文环境
如果没有相应的前因后果,编译器也不知道我们表达是具体是哪个接口。编译器可以通过
-
根据局部变量的赋值得知
Runnable r = ()-> xxxx;
-
根据调用方法的参数得知
new Thread(()-> xxxx).start();
-
-
Lambda表达式和匿名内部类的比较
- lambda只能用在接口,匿名内部类可以用在接口、抽象类、具体类
- lambda只有在接口内只有一个抽象方法可以用,匿名内部类无限制
- 匿名内部类在编译时会单独生成一个字节码文件(可参照博客的匿名内部类文章),lambda是运行时动态生成