目录
1 Lambda表达式简介
1.1 Lambda表达式是什么
1.2 使用Lambda表达式实现Runnable接口
2 Lambda表达式语法
2.1 Lambda表达式基础语法
2.2 Lambda表达式基础语法扩展
2.3 Lambda表达式简写
JDK1.8是目前最流行的JDK版本,在这一个版本中引入了Lamda表达式。Lambda表达式可以简化代码,让我们的代码更为优雅,而Lambda表达式之所以“优雅”,是因为使用Lambda表达式可以对接口进行简洁的实现,Lamdba表达式本身就是一个匿名函数。
在Java中,线程可以通过将实现了Runnable接口的对象作为Thread类构造函数的参数进行创建,比如以下代码。
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread(new MyTest());
thread.start();
}
}
class MyTest implements Runnable {
@Override
public void run() {
System.out.println("执行线程内容");
}
}
当然,也可以使用匿名函数的形式去创建一个线程,使代码的编写更加灵活,如以下代码所示。
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("执行线程内容");
}
});
thread.start();
}
}
在上面的代码中,Runnable是一个接口,直接使用new去创建对象,也必须实现接口中的方法,这里就是匿名函数。而对于匿名函数的实现我们就可以用到Lambda表达式,如以下代码所示。
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("执行线程内容");
});
thread.start();
}
}
在上面使用创建线程简述了Lambda表达式的用法,这里详细描述Lambda表达式的基础语法。
Thread thread = new Thread(() -> {
System.out.println("执行线程内容");
});
以这一段代码作为参考
():表示的是参数的列表,Runnable接口当中的run()方法没有参数,所以()里面是没有参数的;
->:Lambda表达式的运算符,指向方法体;
{}:用来描述方法体。
所以,这里new Thread()中代码段的意思就是创建了一个Runnable接口的实现类,并且实现了接口中无参的抽象方法run,方法体为System.out.println("执行线程内容")。
为什么这里并没有出现Runnable这一个名称程序却知道实现的是Runnble接口,而如果这一个接口中有两个或者多个抽象类程序会怎么解析?对于这两个疑问,首先可以查看Thread类的源码,就是下面的代码段。
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
这是Thread类单个参数的构造方法,参数就是Runnable,所以这里使用Lambda表达式程序可以知道这里实现的Runnbale接口。而对于一个接口中有多个抽象方法的问题,Lambda表达式有这样的使用要求,就是在接口中有且只有一个抽象方法,如果Runnble接口中有两个或者多个抽象方法我们是不能这么用的。并且,打开Runnable接口的源码我们可以发现,在interface上有一个注解@FunctionalInterface,从名称可以看出这个注解的意思是函数式接口,也就是说这个接口里面只能有一个方法,否则会报错。
上面以class Thread与interface Runnable为例介绍了抽象方法在无参、无返回值情况下的实现,介绍了Lambda表达式的基础语法,这里就对Lambda表达式的语法进行一个扩展介绍。
(1)以一个参数,没有返回值的抽象方法举例,首先声明这样一个接口,如以下代码所示。
@FunctionalInterface
public interface NoReturnOneParamInterface {
void test(int num);
}
使用Lambda表示式创建这个接口的实现对象,可以这样写。
public class Test01 {
public static void main(String[] args) {
NoReturnOneParamInterface noReturnOneParamInterface = (int num) -> {
System.out.println(num);
};
noReturnOneParamInterface.test(100); // 结果为在控制台打印了100
}
}
(2)以两个参数,没有返回值的抽象方法举例,接口声明及方法实现方式如下。
@FunctionalInterface
public interface NoReturnTwoParamInterface {
void test(int a, int b);
}
public class Test01 {
public static void main(String[] args) {
NoReturnTwoParamInterface noReturnTwoParamInterface = (int a, int b) -> {
System.out.println(a + b);
};
noReturnTwoParamInterface.test(100, 1000); // 结果为在控制台打印了1100
}
}
(3)以任意参数,有返回值的抽象方法举例,接口声明及方法实现方式如下。
@FunctionalInterface
public interface HasReturnTwoParamInterface {
int test(int a, int b);
}
public class Test01 {
public static void main(String[] args) {
HasReturnTwoParamInterface hasReturnTwoParamInterface = (int a, int b) -> {
System.out.println(a + b);
return a + b;
};
int test = hasReturnTwoParamInterface.test(100, 1000); // 此时int变量的值为1100
System.out.println(test);
}
}
Lambda表达式在一定程度上精简了代码,并且在上面所提到的语法基础上还有一些简写语法,有代码洁癖的人士也许会很喜欢。
(1)参数类型简写
由于方法参数类型在接口定义时早已声明,在编译时JVM是可以知道方法参数类型的,所以在使用Lambda表达式去写有参的匿名函数时可以省略调参数类型。当然,如果要省去参数类型必须该方法的所有参数的类型都不写,否则通不过编译。示例为如下代码。
public class Test01 {
public static void main(String[] args) {
HasReturnTwoParamInterface hasReturnTwoParamInterface = (a, b) -> {
System.out.println(a + b);
return a + b;
};
int test = hasReturnTwoParamInterface.test(100, 1000); // 此时int变量的值为1100
System.out.println(test);
}
}
(2)方法体只有一行时可以省去大括号
这里意思就是说当抽象方法的实现只有一个分号时可以省去包围方法体的大括号,如下代码所示。
public class Test01 {
public static void main(String[] args) {
NoReturnOneParamInterface noReturnOneParamInterface = (a) -> System.out.println("hello world");
noReturnOneParamInterface.test(1000);
}
}
需要注意的是,如果是在省去了大括号并且唯一的一条语句是一个return,则必须省去return关键字,当然省去return关键字还是会返回的。
(3)参数只有一个时可以省去包围参数的小括号
没错,这样也是可以运行的。
public class Test01 {
public static void main(String[] args) {
NoReturnOneParamInterface noReturnOneParamInterface = a -> System.out.println("hello world");
noReturnOneParamInterface.test(1000);
}
}