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

 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. steam 数据转换

    目录 数组和集合互转 数组转集合 方法一 遍历 方法二 asList 方法三 steam 集合转数组 方法一 循环 方法二 toArray 方法三 steam 小结 string转为Character ...

  2. Git 实用操作:重写 Commit 历史

    当我们修改完代码,提交了一个 commit,然后发现改错了,怎么修正?下面分两种情况来讨论:修正最近一次提交,和修正历史多个提交. 修正最近一次提交 如果发现刚刚提交的内容有错误,当场再修改一下再提交 ...

  3. FastJSON解析JSON的时候保证深堆的顺序

    普通的JSONObject.parseObject(),解析的时候,底层采用HashMap解析所以是无序的, JSONObject params = JSONObject.parseObject(ex ...

  4. 利用ANSI转义序列在控制台输出彩色文字

    说明:无论什么语言,只要你的终端能够解释ANSI转义序列(大多数的类unix终端仿真器都能够解释ANSI转义序列,win32控制台则不支持),就能够使用ANSI转义序列输出颜色.这个功能看似鸡肋,但只 ...

  5. Agumaster 将爬虫取股票名称代号子系统分出来成agumaster_crawler, 两系统通过RabbitMq连接

    agumaster_crawler系统负责启动爬虫取得数据,之后便往队列中推送. agumaster_crawler系统中pom.xml关于RabbitMq的依赖是: <!-- RabbitMq ...

  6. Tomcat源码分析(类加载与类加载器)

    Tomcat的挑战 Tomcat上可以部署多个项目 Tomcat的一般部署,可以通过多种方式启动一个Tomcat部署多个项目,那么Tomcat在设计时会遇到什么挑战呢? Tomcat运行时需要加载哪些 ...

  7. SpringMVC-Controller&RestFul

    Controller与RestFul 目录 Controller与RestFul 1. Controller 1. 控制器Controller 2. 利用接口定义控制器 1. 实现Controller ...

  8. 图解冒泡排序及算法优化(Java实现)

    冒牌排序 基本思想 定义:冒泡排序的英文是bubblesort,它是一种基础的交换排序 原理:每次比较两个相邻的元素,将较大的元素交换至右端 (升序排序) 思路:相邻的元素两两比较,当一个元素大于右侧 ...

  9. JVM垃圾回收行为的并行与并发

    程序的并行和并发 程序的并发(Concurrent) 在操作系统中,是指一个时间段中有几个程序都处于己启动运行到运行完毕之间,且这几个程序都是在同一个处理器_上运行. 并发不是真正意义上的“同时进行” ...

  10. Docker实战(5)升级Docker版本后的报错

    出现情况:因我升级了Centos内核后docker服务无法开启,所做重装处理但还是无效,最终将docker服务做了升级,升级步骤我会放置下面,但在启动老版本容器又出现Error response fr ...