一看就懂:Java 之 Lamda 写法

tech2025-10-07  4

文章目录

概述优势示例释义拓展示例示例1示例2 变量作用域方法变量类变量 结尾语

概述

现在,很多同学已经接受并熟悉了 Java 的 Lamda 写法,但可能有些同学还是一头雾水。 这里,我抛砖引玉,来对 Java Lamda 写法做一个简单的介绍:

首先 Lamda 写法的固定格式为:参数 -> 语句块

另外 Lamda 语法是出现在Java8及其以后的,Java8以前是不涉及的,所以JDK1.7及其以前版本这种写法编译是会被报错的。

优势

那么Lamda 写法有哪些优势呢?

首先,他简化了代码,将以前很多行的代码简化为几行或者一行,使得代码看上去更加的简介;

另外,Lamda 算法对并行运算非常具有优势,某些实现用 Lamda 方式会更加高效。

示例

如果一个接口只有一个实现方法,我们称这种接口叫做函数式接口。 那么我们通常会以匿名内部类的方式去实现。

比如:我们常用的多线程去异步实现某个功能的时候,常常会使用如下方式:

new Thread(new Runnable() { @Override public void run() { System.out.println("异步功能实现"); } }).start();

这里的 Runable 接口就一个run() 实现方法,源码如下图:

那么这种条件下,就可以简化为 Lamda 写法,具体效果如下:

new Thread(() -> System.out.println("异步实现功能")).start();

我们可以看见:Lamda 写法的代码量已经浓缩为了一行,确实简洁了不少。

释义

那么如何理解上面这句 Lamda 写法呢?

(1)我们可以看到,变化的只是参数接口匿名实现类的写法,外面外并未有任何变化;

(2)由于 Thread 类里面就一个以接口为参数的方法,所以省去了接口名 Runable;

(3)由于 Ruanble 接口里面就一个 run() 方法定义,故而省去了方法名;

(4)由于 run() 方法定义里未有任何参数,故而 Lamda 写法就只有以一个 () 开头了;

(5) 中间的箭头 -> 是 Lamda 标识符,读作 “goes to”;

(6)箭头后面就是实现方式了,这个同以前代码实现。

拓展示例

示例1

那么,当一个接口的唯一方法涉及多个参数,此时 Lamda 写法又该怎么样呢?

我们不妨创建一个 MyService,里面包含一个带有参数的方法定义:

public interface MyService { public void say(String name); }

然后我们创建一个 Test 类,并在类里面添加一个该接口为参数的 test() 方法,以及主方法进行测试:

Java 8 以前的写法:

public class Test { public static void main(String[] args){ test(new MyService() { @Override public void say(String name) { System.out.println("hello : " + name); } }); } public static void test(MyService service) { service.say("jack"); } }

程序运行结果为如下所示:

Java 8 Lamda 写法:

public class Test { public static void main(String[] args){ test((name) -> System.out.println("hello : " + name)); } public static void test(MyService service) { service.say("jack"); } }

运行结果,同样为:

经过上面两个例子,我们已经证实了,两种写法的运行效果完全是可以等价的,Lamda 写法看起来也更简洁。

另外,当参数只有一个的时候,参数的括号也可以省去不写,例如,上面的 Lamda 写法还可以进一步简写:

test(name -> System.out.println("hello : " + name));

同理,如果接口的方法有多个参数的时候,Lamda 参数括号里也需要传递多个参数。

示例2

我们将接口里面的 say(String name) 方法,增加一个参数 age,改为如下:

public interface MyService { public void say(String name, int age); }

那么对应的方法调用就成为了如下:

Java 8 前写法:

public class Test { public static void main(String[] args){ test(new MyService() { @Override public void say(String name, int age) { System.out.println("hello : " + name + ", I am " + age); } }); } public static void test(MyService service) { service.say("jack", 28); } }

Java 8 Lamda 写法:

public class Test { public static void main(String[] args){ test((name, age) -> System.out.println("hello : " + name + ", I am " + age)); } public static void test(MyService service) { service.say("jack", 28); } }

两种写法的输出结果都是:

可以看到,随着接口方法 say() 里的参数增加,Lamda 参数括号里面的参数也相应增加。

同理,当 Lamda 语句块里面只有一条语句的时候,我们可以通常省略语句块符号{},如上面的 Lamda语句:

test((name, age) -> System.out.println("hello : " + name + ", I am " + age));

但如果涉及多条语句的时候,就需要增加语句块 {}了,比如我们将 name 和 age 分别打印的话,则对应的 Lamda 写法为:

test((name, age) -> { System.out.println("My name is"+ name); System.out.println("I am "+ age); });

变量作用域

方法变量

首先,Lamda 语句中引用外层方法中的变量的时候,是不允许修改其变量值的,具体什么意思呢?我们不妨接着往下看。

我们在上一步中的方法增加一个变量; 然后我们在 Lamda 语句块中将其值修改下: 可以看到:编译器这时候报了错,说明其值是不允许被修改的:

这就说明: Lamda 不允许修改所在外层方法里的变量;

类变量

然后,我们将变量的位置挪动下,将方法变量移动到为类的变量(这里由于方法是 static 的,所以我们为了能直接访问到变量,也加上 static 修饰)。 可以看到,这时编译器并未进行报错,说明 Lamda 语句块中是可以修改其类成员变量(final 修饰除外)。

我们运行程序: 可以看到,确实是我们修改后的值。

结尾语

上面所讲的主要是 Lamda 写法之匿名内部类,这是一个较为容易理解 Lamda 写法的入门,谢谢大家!

最新回复(0)