lambda - 类文件在文件系统中的含义

标签 lambda java-8 method-reference

我正在研究 lambda 表达式,这本书说明了一个使用 lambda 表达式的 toString() 方法的示例。

Supplier<ArrayList<String>> s1 = ArrayList<String>::new;
ArrayList<String> a1 = s1.get();
System.out.println(s1);
//Output: functionalinterface.BuiltIns$$Lambda$1/791452441@1fb3ebeb

它将输出的含义解释为,

This actually does mean something. Our test class is named BuiltIns , and it is in a package that we created named functionalinterface . Then comes $$ , which means that the class doesn’t exist in a class file on the file system. It exists only in memory.

最后几句的意思没看懂。你能表达出来吗?

来源:OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide, Jeanne Boyarsky, Scott Selikoff

最佳答案

好吧,这本书有点误导。该声明确实正确,但有一个小的更正。它假设如果您在类名中包含$,它会自动创建(不是由您创建);这可能不是事实。

例如假设这个例子:

public class TestSO {

   public static void main(String[] args) {
      Test t = new Test() {
      };
   }

   static class Test {}
}

您已经创建了一个匿名内部类,它实际上是一个由编译器创建的普通类。如果编译 TestSO,您将看到一个名为 TestSO\$1.class 的类,它是为您创建的。如果您使用 javap -c -p TestSO\$1.class 检查它的外观,您将看到如下内容:

final class TestSO$1 extends TestSO$Test { ... 

但是同时声明包含$ 符号的类/方法是完全合法的:

static class $$Test2$$ {}

因此 $$ 的存在并不强烈表明该类是由编译器/运行时生成的。这也是一个实现细节,有一天可能会改变......

同时这本书是正确的,类不存在于文件系统的类文件中。它只存在于内存中

Supplier 是一个接口(interface),您还没有提供实现它的类,是吗?那么接下来发生的事情很有趣。

我不打算详细介绍,但这里有一个简化的解释。

如果反编译您的示例 (javap -p -c -v TestSO.class),您将看到如下一行:

invokedynamic #2,  0  // InvokeDynamic #0:get:()Ljava/util/function/Supplier;

invokedynamic 所做的是让runtime 决定如何提供该Supplier 的实际实例。 在运行时会创建一个实际类来实现所使用的Supplier

您可以通过运行它时使用的命令来查看该类的外观:

-Djdk.internal.lambda.dumpProxyClasses=/Your/Path/Here

作为该路径的结果,您将看到一个名为的类:

TestSO$$Lambda$1.class 

再次,如果您使用 javap -c -p TestSO\$\$Lambda\$1.class 反编译它:

 final class TestSO$$Lambda$1 
         implements java.util.function.Supplier {....

作者想说的是,在运行时会为您生成一个,它实现了Supplier 接口(interface),但它不是您创建的。

关于lambda - 类文件在文件系统中的含义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44475789/

相关文章:

python - 在Python中的pandas数据框中使用lambda函数使用多种文本格式?

c++ - 嵌套的 lambda 函数

c# - Blazor - 如何动态创建输入然后读取它们的值

java - 使用 Java 8 Streams API 列出迭代和设置值

generics - Java 8 [无法推断类型变量]问题

java - FileFilter Java 8 的方法引用

python - 奇怪的未知 lambda 语法

Java 8 读取文件列表,但文件保持打开状态,直到服务器卡住

java - 如何使用流而不是循环来迭代jsonarray?

java - 如何在 UnaryOperator java 8 中使用引用方法