首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java 8 Lambda表达式编译为什么?

Java 8 Lambda表达式编译为什么?
EN

Stack Overflow用户
提问于 2014-02-18 23:40:46
回答 1查看 12.5K关注 0票数 25

考虑下面的Java 8代码片段。

代码语言:javascript
复制
public static void main(String[] args) {            
   List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);

   Consumer<Integer>  consumer = x -> System.out.print(x);  

   integers.forEach(consumer);
}

Consumer<Integer> consumer = x -> System.out.print(x)将被编译成什么?

我知道Lambdas不是作为匿名内部类实现的。但是,Consumer<Integer>是一个接口,因此x -> System.out.print(x)必须生成某种类型的对象,但不清楚生成的是哪种类型的对象。

Java 8中有没有某种新类型的对象来表示lambda表达式?

eclipse更新这里是反编译的程序,该程序是用eclipse java8编译器编译的,下面的输出是当您打开一个类文件时eclipse的输出。

看起来,在包含拉姆达表达式private static synthetic void lambda$0(java.lang.Integer x);的类上,拉姆达表达式变成了一个静态方法

代码语言:javascript
复制
// Compiled from Example.java (version 1.8 : 52.0, super bit)
public class Example {

  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public Example();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 7]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: Example

  // Method descriptor #15 ([Ljava/lang/String;)V
  // Stack: 4, Locals: 3
  public static void main(java.lang.String[] args);
     0  iconst_5
     1  anewarray java.lang.Integer [16]
     4  dup
     5  iconst_0
     6  iconst_1
     7  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    10  aastore
    11  dup
    12  iconst_1
    13  iconst_2
    14  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    17  aastore
    18  dup
    19  iconst_2
    20  iconst_3
    21  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    24  aastore
    25  dup
    26  iconst_3
    27  iconst_4
    28  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    31  aastore
    32  dup
    33  iconst_4
    34  iconst_5
    35  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    38  aastore
    39  invokestatic java.util.Arrays.asList(java.lang.Object[]) : java.util.List [22]
    42  astore_1 [integers]
    43  invokedynamic 0 accept() : java.util.function.Consumer [31]
    48  astore_2 [consumer]
    49  getstatic java.lang.System.out : java.io.PrintStream [32]
    52  aload_2 [consumer]
    53  invokevirtual java.lang.Object.getClass() : java.lang.Class [38]
    56  invokevirtual java.lang.Class.getCanonicalName() : java.lang.String [42]
    59  invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
    62  getstatic java.lang.System.out : java.io.PrintStream [32]
    65  aload_2 [consumer]
    66  invokevirtual java.lang.Object.getClass() : java.lang.Class [38]
    69  invokevirtual java.lang.Class.getTypeName() : java.lang.String [54]
    72  invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
    75  aload_1 [integers]
    76  aload_2 [consumer]
    77  invokeinterface java.util.List.forEach(java.util.function.Consumer) : void [57] [nargs: 2]
    82  return
      Line numbers:
        [pc: 0, line: 10]
        [pc: 43, line: 12]
        [pc: 49, line: 14]
        [pc: 62, line: 15]
        [pc: 75, line: 17]
        [pc: 82, line: 18]
      Local variable table:
        [pc: 0, pc: 83] local: args index: 0 type: java.lang.String[]
        [pc: 43, pc: 83] local: integers index: 1 type: java.util.List
        [pc: 49, pc: 83] local: consumer index: 2 type: java.util.function.Consumer
      Local variable type table:
        [pc: 43, pc: 83] local: integers index: 1 type: java.util.List<java.lang.Integer>
        [pc: 49, pc: 83] local: consumer index: 2 type: java.util.function.Consumer<java.lang.Integer>

  // Method descriptor #73 (Ljava/lang/Integer;)V
  // Stack: 2, Locals: 1
  private static synthetic void lambda$0(java.lang.Integer x);
    0  getstatic java.lang.System.out : java.io.PrintStream [32]
    3  aload_0 [x]
    4  invokevirtual java.io.PrintStream.print(java.lang.Object) : void [74]
    7  return
      Line numbers:
        [pc: 0, line: 12]
      Local variable table:
        [pc: 0, pc: 8] local: x index: 0 type: java.lang.Integer

  Inner classes:
    [inner class info: #96 java/lang/invoke/MethodHandles$Lookup, outer class info: #98 java/lang/invoke/MethodHandles
     inner name: #100 Lookup, accessflags: 25 public static final]
Bootstrap methods:
  0 : # 89 arguments: {#90,#93,#94}
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-18 23:52:52

current draft of the Java 8 Language Specification声明(15.27.4章)

λ表达式的值是对具有以下属性的类的实例的引用:

如果目标类型是交集类型,则intersection.

  • The类的每个其他接口元素声明一个方法,该方法覆盖函数接口超类型的抽象方法(并且,潜在地,其superinterfaces).

  • The方法的参数类型、返回类型和抛出类型的一些其他方法由接口的类型给出。
  • 如果是表达式,则方法主体具有求值的效果;如果是块,则执行
  • 主体;如果需要结果,则从方法返回该结果。
  • 该类不会重写上述一个或多个接口的任何其他方法,除非它可以重写Object类的方法。

请注意,除了字节码应该支持上面的规范之外,JLS并没有说明应该如何编译代码。

因此,lambda表达式返回的对象

代码语言:javascript
复制
x -> System.out.print(x);  

将是遵循上述规则的类的实例。

考虑到你的评论

代码语言:javascript
复制
consumer.getClass()

返回以下类

代码语言:javascript
复制
Example$$Lambda$1/1072591677

它似乎正在生成一个特定于lambda表达式的类似代理的类。

请看这里:

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21858482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档