| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 4417652 commit d16661d
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -171,6 +171,66 @@ Lambda是Java 8最大的卖点。它具有吸引越来越多程序员到Java平 | |||
| 171 | 171 | void get(int i,String j); | |
| 172 | 172 | } | |
| 173 | 173 | ||
| 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 | + | ||
| 174 | 234 | ### 函数式接口 | |
| 175 | 235 | ||
| 176 | 236 | 所谓的函数式接口就是只有一个抽象方法的接口,注意这里说的是抽象方法,因为Java8中加入了默认方法的特性,但是函数式接口是不关心接口中有没有默认方法的。 一般函数式接口可以使用@FunctionalInterface注解的形式来标注表示这是一个函数式接口,该注解标注与否对函数式接口没有实际的影响, 不过一般还是推荐使用该注解,就像使用@Override注解一样。 | |
| Back | FazBrowse Home | New Git URL |
0 commit comments