Lambda表达式的简化代码的过程
使用外部类
package com.cj.lambda;
public class TestLambda implements Runnable{
@Override
public void run() {
System.out.println("这是使用外部类实现Runable接口...");
}
}
class Test{
public static void main(String[] args){
TestLambda testLambda = new TestLambda();
testLambda.run();
}
}
使用静态内部类
package com.cj.lambda;
public class Test{
public static class TestLambda implements Runnable{
@Override
public void run() {
System.out.println("这是使用静态内部类实现Runable接口...");
}
}
public static void main(String[] args){
TestLambda testLambda = new TestLambda();
testLambda.run();
}
}
使用匿名内部类
省略了类对函数式接口的实现,直接new需要被实现的接口,实现接口中的方法即可
package com.cj.lambda;
public class Test{
public static void main(String[] args){
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("这是使用匿名内部类实现Runable接口...");
}
};
runnable.run();
}
}
使用Lambda表达式
在匿名内部类的基础上省略了new接口的过程,只保留接口实现方法的方法体即可
package com.cj.lambda;
public class Test{
public static void main(String[] args){
Runnable runnable = () ->{
System.out.println("这是使用Lambda表达式实现Runable接口...");
};
runnable.run();
}
}
Lambda表达式的解释
语法
( 参数1, 参数2, ... ) -> { 方法体 }
-
Java 11 后,还可以使用
var
关键字作为参数类型。 -
-> 是Lambda表达式的标识符
-
当方法体中只有一个语句时可以连同大括号一起省略
() -> System.out.println("Lambda表达式...")
Lambda表达式的作用
为变量赋值
public static void main(String[] args){
Runnable runnable = () ->{
System.out.println("这是使用Lambda表达式实现Runable接口...");
};
runnable.run();
}
作为方法的参数
new Thread(() -> System.out.println("Lambda...")).start();
直接作为return的结果
static FileFilter getFilter(String ext)
{
return (pathname) -> pathname.toString().endsWith(ext);
}
初始化数组元素
final PathMatcher matchers[] =
{
(path) -> path.toString().endsWith("txt"),
(path) -> path.toString().endsWith("java")
};
Lambda表达式的使用注意事项
Lambda 表达式的作用域范围
-
Lambda 表达式中要用到的,但又未在 Lambda 表达式中声明的变量,必须声明为 final 或者是 effectively final,否则就会出现编译错误。
-
如何在Lambda表达式中修改外部变量的值
-
将变量声明为static
public class Test { static int temp = 10; public static void main(String[] args) { Runnable r = () -> { temp = 5; System.out.println(temp); }; new Thread(r).start(); } }
-
将变量声明为AtomicInteger
AtomicInteger类型的变量可以确保int值的修改是原子性的,可以使用get(),set()方法操作int的值
public class Test { public static void main(String[] args) { final AtomicInteger temp = new AtomicInteger(10); Runnable r = () -> { temp.set(5); System.out.println(temp.get()); }; new Thread(r).start(); } }
-
使用数组
public class Test { public static void main(String[] args) { final int [] temp = {10}; Runnable r = () -> { temp[0] = 5; System.out.println(temp); }; new Thread(r).start(); } }
-
Lambda 中使用 this 关键字
Lambda 表达式并不会引入新的作用域,这一点和匿名内部类是不同的。也就是说,Lambda 表达式主体内使用的 this 关键字和其所在的类实例相同。
public class LamadaTest {
public static void main(String[] args) {
new LamadaTest().work();
}
public void work() {
System.out.printf("this = %s%n", this);
Runnable r = new Runnable()
{
@Override
public void run()
{
System.out.printf("this = %s%n", this);
}
};
new Thread(r).start();
new Thread(() -> System.out.printf("this = %s%n", this)).start();
}
}
注意:%s
代表当前位置输出字符串,%n
代表换行符,也可以使用 \n
代替,但 %n
是跨平台的。
输出结果:可以发现Lambda表达式中输出结果和原类的输出结果一致,但是与匿名内部类不一致
this = com.cmower.java_demo.journal.LamadaTest@3feba861
this = com.cmower.java_demo.journal.LamadaTest$1@64f033cb
this = com.cmower.java_demo.journal.LamadaTest@3feba861