文件系统上类文件的含义

时间:2017-06-10 16:51:26

标签: lambda java-8 method-reference

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

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

它解释了输出的含义,

  

这实际上意味着什么。我们的测试类名为BuiltIns,   它位于我们创建的名为functionalinterface的包中。   然后是$$,这意味着类在类中不存在   文件系统上的文件。它只存在于内存中。

我不明白最后句子的意思。你能表达一下吗?

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

3 个答案:

答案 0 :(得分:3)

这本书略微误导。声明它确实是正确的,但有一个小的修正。 假定如果您在类名中有$,则会自动创建(不是您);这可能不是事实。

例如假设这个例子:

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$$ {}

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

现在同时这本书是正确的the class doesn’t exist in a class file on the file system. It exists only in memory

Supplier是一个接口,你没有提供实现它的类,对吗?接下来发生的事情很有趣。

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

如果您对示例(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 {....

作者试图说的是,在运行时会为您生成class来实现供应商界面,但不是您创建了它的人。

答案 1 :(得分:2)

这个引用试图用更简单或更通俗的术语来解释某些东西,避免过于正式,但结果可能被称为灾难性的。

这个名字实际上没有任何意义。实例的类为lambda表达式或方法引用is intentionally unspecified提供,因此它的名称也是如此。甚至未指定在执行toString()时隐式调用的System.out.println(s1);方法是否会产生“classname @ hashcode”输出。

是否涉及文件系统,无关紧要。正确和实际的一点是,在编译应用程序时,该实例的类不属于Java编译器创建的类。相反,它由JRE在运行时以特定于实现的方式提供。 OpenJDK确实提供了一个生成的类,其恰好具有包含lambda表达式和$$的类的名称,但是,如上所述,这是一个实现细节。而且,as explained by Eugene,美元符号是Java标识符的合法部分,因此两个美元符号的存在并不是特定属性。

答案 2 :(得分:1)

  

创建类时,键入# AppBundle/Admin/ShapeAdmin.php protected function configureFormFields(FormMapper $formMapper) /** @var Shape $shape */ $shape = $this->getSubject(); // add form fields for both types $formMapper ->add('service', null, ['disabled' => true]); // add specific form fields if ($shape instanceof Rectangle) { // custom rectangle form fields } elseif ($shape instanceof Circle { // custom circle form fields } } 文件并将其编译为   .java个文件。两者都是存在于您的某个地方的实际文件   文件系统。 .class 表明它不同。没有$$   文件系统。 相反,Java为我们创建了类。就是这样   不必输入类,只能提供lambda   表达

其作者Ms.Boyarsky

回答