Skip to content

Commit d16661d

Browse files
author
李文浚
committed
添加《Java8新特性终极指南.md》中的Lambda表达式和匿名内部类的区别描述
1 parent 4417652 commit d16661d

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

docs/java/basic/21、Java8新特性终极指南.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,66 @@ Lambda是Java 8最大的卖点。它具有吸引越来越多程序员到Java平
171171
void get(int i,String j);
172172
}
173173

174+
接下来看看Lambda和匿名内部类的区别
175+
176+
匿名内部类仍然是一个类,只是不需要我们显式指定类名,编译器会自动为该类取名。比如有如下形式的代码:
177+
178+
public class LambdaTest {
179+
public static void main(String[] args) {
180+
new Thread(new Runnable() {
181+
@Override
182+
public void run() {
183+
System.out.println("Hello World");
184+
}
185+
}).start();
186+
}
187+
}
188+
189+
编译之后将会产生两个 class 文件:
190+
191+
LambdaTest.class
192+
LambdaTest$1.class
193+
194+
使用 javap -c LambdaTest.class 进一步分析 LambdaTest.class 的字节码,部分结果如下:
195+
196+
public static void main(java.lang.String[]);
197+
Code:
198+
0: new #2 // class java/lang/Thread
199+
3: dup
200+
4: new #3 // class com/example/myapplication/lambda/LambdaTest$1
201+
7: dup
202+
8: invokespecial #4 // Method com/example/myapplication/lambda/LambdaTest$1."<init>":()V
203+
11: invokespecial #5 // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
204+
14: invokevirtual #6 // Method java/lang/Thread.start:()V
205+
17: return
206+
207+
可以发现在 4: new #3 这一行创建了匿名内部类的对象。
208+
209+
而对于 Lambda表达式的实现, 接下来我们将上面的示例代码使用 Lambda 表达式实现,代码如下:
210+
211+
public class LambdaTest {
212+
public static void main(String[] args) {
213+
new Thread(() -> System.out.println("Hello World")).start();
214+
}
215+
}
216+
217+
此时编译后只会产生一个文件 LambdaTest.class,再来看看通过 javap 对该文件反编译后的结果:
218+
219+
public static void main(java.lang.String[]);
220+
Code:
221+
0: new #2 // class java/lang/Thread
222+
3: dup
223+
4: invokedynamic #3, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable;
224+
9: invokespecial #4 // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
225+
12: invokevirtual #5 // Method java/lang/Thread.start:()V
226+
15: return
227+
228+
从上面的结果我们发现 Lambda 表达式被封装成了主类的一个私有方法,并通过 invokedynamic 指令进行调用。
229+
230+
因此,我们可以得出结论:Lambda 表达式是通过 invokedynamic 指令实现的,并且书写 Lambda 表达式不会产生新的类。
231+
232+
既然 Lambda 表达式不会创建匿名内部类,那么在 Lambda 表达式中使用 this 关键字时,其指向的是外部类的引用。
233+
174234
### 函数式接口
175235

176236
所谓的函数式接口就是只有一个抽象方法的接口,注意这里说的是抽象方法,因为Java8中加入了默认方法的特性,但是函数式接口是不关心接口中有没有默认方法的。 一般函数式接口可以使用@FunctionalInterface注解的形式来标注表示这是一个函数式接口,该注解标注与否对函数式接口没有实际的影响, 不过一般还是推荐使用该注解,就像使用@Override注解一样。

0 commit comments

Comments
 (0)