先看一下匿名内部类长什么样子:

 1 package com.jvm.demo.test2;
2
3 public class InnerClassTest {
4
5 public static void main(String[] args) {
6 new Thread(new Runnable() {
7 @Override
8 public void run() {
9 System.out.print("hello world!");
10 }
11 }).start();
12 }
13
14 }

  再看一下lambda表达式长什么样子

1 package com.jvm.demo.test2;
2
3 public class LambdaTest {
4
5 public static void main(String[] args) {
6 new Thread(() -> System.out.print("hello world!")).start();
7 }
8
9 }

  是不是长的很像,一眼能看出区别就在于参数的传递上,匿名内部类是传递的对象,而lambda表达式是传递的函数,那么我们是不是可以认为

lambda实际上就是一个语法糖,简化了部分代码?这就需要我们去看一下底层实现了。

  先把两个类都编译一遍,然后javap反编译查看class码,先来看看匿名内部类的实现:

  javap -v -p -l -s -c InnerClassTest

  

  0-11行,可以看到是分别创建了一个Thread对象和一个InnerClassTest$1对象,InnerClassTest$1对象是什么呢?可以看下面

  这下就忽然开朗了,InnerClassTest$1是一个单独的类文件,我们在目录下面也是可以看到的:

由此我们可以得出结论:匿名内部类的实现是通过创建一个类文件来实现的,那么LambdaTest又是如何实现的呢?

javap -v -p -l -s -c LambdaTest.class

  

  0-4行,调用了invokedynamic指令,invokedynamic指令是一个动态调用指令,该指令调用的代码在编译阶段不确定,在第一次运行的时候才会确定。

  4: invokedynamic #3,  0  其中的#3指向常量池中的#3:

  #0指向引导方法的0行:

  引导方法是invokedynamic都会调用的一个方法,从上面可以看出引导方法里面会调用类metafactory里面的方法,我们先去看下metafactory这个类,

这个类是一个内部类,在LambdaMetafactory里面:

  这里主要是调用了InnerClassLambdaMetafactory方法,进去看看:

  可以看出这里是根据传入的方法特征(返回值和参数)来动态构造一个类,该类的命名规则是

targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();

  最终这个类会被返回出去:

 

  然后返回CallSite调用点,以便多次调用。

  之前就有人说过Lambda表达式过多影响程序性能,但是现在看来不是这样的,Lambda实际只会在第一次调用的时候动态生成类,之后调用就不会重新生成了。

  

匿名内部类和Lambda表达式是一样的吗?的更多相关文章

  1. java8 探讨与分析匿名内部类、lambda表达式、方法引用的底层实现

    问题解决思路:查看编译生成的字节码文件 目录 测试匿名内部类的实现 小结 测试lambda表达式 小结 测试方法引用 小结 三种实现方式的总结 对于lambda表达式,为什么java8要这样做? 理论 ...

  2. Java 从匿名内部类到Lambda表达式

    匿名内部类和Lambda表达式有很多类似之处,首先都是在使用的时候才对接口进行实现,只是Lambda接口中只能由一个需要被实现的方法. 所有的Lambda表达式都可以 由匿名内部类改写: interf ...

  3. Java基础学习总结(69)——匿名内部类与Lambda表达式

    前言 Java Labmda表达式的一个重要用法是简化某些匿名内部类(Anonymous Classes)的写法.实际上Lambda表达式并不仅仅是匿名内部类的语法糖,JVM内部是通过invokedy ...

  4. 17.继承 and18.接口和多态 内部类 匿名内部类,Lambda表达式

    1. 继承 1.1 继承的实现(掌握) 继承的概念 继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法 实现继承的格式 继承通过extends实现 ...

  5. 0028 Java学习笔记-面向对象-Lambda表达式

    匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...

  6. 深入探索Java 8 Lambda表达式

    2014年3月,Java 8发布,Lambda表达式作为一项重要的特性随之而来.或许现在你已经在使用Lambda表达式来书写简洁灵活的代码.比如,你可以使用Lambda表达式和新增的流相关的API,完 ...

  7. 掌握 Java 8 Lambda 表达式

    Lambda 表达式 是 Java8 中最重要的功能之一.使用 Lambda 表达式 可以替代只有一个函数的接口实现,告别匿名内部类,代码看起来更简洁易懂.Lambda 表达式 同时还提升了对 集合 ...

  8. 初探Lambda表达式/Java多核编程【2】并行与组合行为

    今天又翻了一下书的目录,第一章在这之后就结束了.也就是说,这本书所涉及到的新的知识已经全部点到了. 书的其余部分就是对这几个概念做一些基础知识的补充以及更深层次的实践. 最后两个小节的内容较少,所以合 ...

  9. Java 8 特性 —— lambda 表达式

    Lambda 表达式 Lambda表达式本质上是一个匿名方法.常见的一个例子是,在 IDEA + JDK8 的环境下按照Java传统的语法规则编写一个线程: new Thread(new Runnab ...

随机推荐

  1. qdu-凑数题(01背包)

    Description 小Q手里有n(n<=1000) 个硬币,每枚硬币有一定的金额(200=>x>=1)他想知道,用这些硬币(每枚硬币只能用一次,但可能会有等面值的用两次) 能组成 ...

  2. Codeforces 1321C Remove Adjacent

    题意 给你一个字符串,字符\(s_i\)可以被伤处当且仅当\(s_{i-1}=s_i-1\)或\(s_{i+1}=s_i-1\).问最多能删几个字符. 解题思路 其实,有个很简单的做法就是从\(z\) ...

  3. 免费获取 IntelliJ IDEA 激活码的 6 种方式!

    你还在满世界找 IntelliJ IDEA 激活码? 破解的不稳定,也是违法的,有安全风险还不一定,不建议大家使用来历不明的补丁. 今天栈长就分享免费获取 IntelliJ IDEA 的 6 种方式, ...

  4. ASP.NET Core 进程内与进程外的性能对比

    ASP.NET Core 进程内与进程外的性能对比 本文内容是<深入去浅出ASP.NET Core>提供的扩展内容,毕竟在书里说进程内外的性能说明对比,对于初学者而言,稍微复杂了点. 我在 ...

  5. Tomcat源码分析(下载、启动)

    1.下载Tomcat源代码: https://tomcat.apache.org/download-80.cgi 2. 解压以及创建必要目录和配置 解压.新建catalina-home目录,同时将目录 ...

  6. HTML绘制表格

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  7. origin Tips

    origin Tips 注意事项 在最初画图时,需要考虑到最好将图片的尺寸限制在 1 张 A4 纸的大小,不然有可能在插入 latex 的时候出问题 . 如何修改图片的尺寸?简而言之就是将画布中的图片 ...

  8. 基于jQuery的鼠标悬停时放大图片的效果制作

    这是一个基于jQuery的效果,当鼠标在小图片上悬停时,会弹出一个大图,该大图会跟随鼠标的移动而移动.这个效果最初源于小敏同志的一个想法,刚开始做的时候只能实现弹出的图片是固定的,不能随鼠标移动,最后 ...

  9. 你还记得 Tomcat 的工作原理么

    SpringBoot 就像一条巨蟒,慢慢缠绕着我们,使我们麻痹.不得不承认,使用了 SpringBoot 确实提高了工作效率,但同时也让我们遗忘了很多技能.刚入社会的时候,我还是通过 Tomcat 手 ...

  10. js图形打印

    1. 打印等边三角形 document.writeln("打印三角形</br>"); for(var i=0;i<5;i++){ for(var j=5;j> ...