Имеет ли лямбда-выражение объект, связанный с ним, и почему «это» не относится к объекту лямбда-выражения?

Я сильно запутался в том, есть ли объект, связанный с лямбда-выражением, или нет, потому что сказано, что «это» в случае лямбда-выражения не относится к объекту лямбда-выражения, потому что лямбда-выражение не имеет никакого объекта. но опять же говорится, что если лямбда-выражение не захватывает переменные из-за пределов области видимости, то один и тот же одноэлементный объект будет использоваться для каждого вызова лямбда-выражения.

Теперь я предполагаю, что будет объект, связанный с лямбда-выражением (я думаю, это ответ на мой первый вопрос, ребята, поправьте меня, если я ошибаюсь), поэтому мой вопрос заключается в том, почему тогда «это» не относится к объекту лямбда-выражения, как это происходит в случае анонимного класса.


ОБНОВЛЕНИЯ: Мои 3 тестовых класса:

import java.util.function.Consumer;

public class LambdaByteCodeAnalysis1 {

    public static void main(String[] args) {
        testConsumer();
    }

    private static void testConsumer() {
        // *** void accept(T t); ***
        testConsumerImpl((value) -> System.out.println("Hello, Mr. " + value));

    }
    private static void testConsumerImpl(Consumer<Object> consumer) {
        consumer.accept("testConsumer");
    }

}


##############
import java.util.function.Consumer;

public class LambdaByteCodeAnalysis2 {

    public static void main(String[] args) {
        testConsumer();
    }

    private static void testConsumer() {
        int testing = 0;
        testConsumerImpl((value) -> {
            System.out.println("Hello, Mr. " + value);
            System.out.println(testing);
        });

    }
    private static void testConsumerImpl(Consumer<Object> consumer) {
        consumer.accept("testConsumer");
    }

}


################
import java.util.function.Consumer;

public class LambdaByteCodeAnalysis3 {

    int testing = 0;

    public static void main(String[] args) {
        testConsumer();
    }

    private static void testConsumer() {
        LambdaByteCodeAnalysis3 lambdaByteCodeAnalysis3 = new LambdaByteCodeAnalysis3();
        testConsumerImpl((value) -> {
            System.out.println("Hello, Mr. " + value);
            System.out.println(lambdaByteCodeAnalysis3.testing);
        });

    }
    private static void testConsumerImpl(Consumer<Object> consumer) {
        consumer.accept("testConsumer");
    }

}

Теперь байт-код в том же порядке:

LambdaByteCodeAnalysis1.class

C:\E_Drive\Projects\SourceCode\Learning\learn\src\com\learn\oracle\LearningJavaLang\ClassesAndObject\LamdaExpression>javap -v LambdaByteCodeAnalysis1
Classfile /C:/E_Drive/Projects/SourceCode/Learning/learn/src/com/learn/oracle/LearningJavaLang/ClassesAndObject/LamdaExpression/LambdaByteCodeAnalysis1.class
  Last modified 15 Aug, 2018; size 1574 bytes
  MD5 checksum d90045ca82de96636d8fc91f54637c32
  Compiled from "LambdaByteCodeAnalysis1.java"
public class LambdaByteCodeAnalysis1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #16.#32        // java/lang/Object."<init>":()V
   #2 = Methodref          #15.#33        // LambdaByteCodeAnalysis1.testConsumer:()V
   #3 = InvokeDynamic      #0:#38         // #0:accept:()Ljava/util/function/Consumer;
   #4 = Methodref          #15.#39        // LambdaByteCodeAnalysis1.testConsumerImpl:(Ljava/util/function/Consumer;)V
   #5 = String             #23            // testConsumer
   #6 = InterfaceMethodref #40.#41        // java/util/function/Consumer.accept:(Ljava/lang/Object;)V
   #7 = Fieldref           #42.#43        // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Class              #44            // java/lang/StringBuilder
   #9 = Methodref          #8.#32         // java/lang/StringBuilder."<init>":()V
  #10 = String             #45            // Hello, Mr.
  #11 = Methodref          #8.#46         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #12 = Methodref          #8.#47         // java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #13 = Methodref          #8.#48         // java/lang/StringBuilder.toString:()Ljava/lang/String;
  #14 = Methodref          #49.#50        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #15 = Class              #51            // LambdaByteCodeAnalysis1
  #16 = Class              #52            // java/lang/Object
  #17 = Utf8               <init>
  #18 = Utf8               ()V
  #19 = Utf8               Code
  #20 = Utf8               LineNumberTable
  #21 = Utf8               main
  #22 = Utf8               ([Ljava/lang/String;)V
  #23 = Utf8               testConsumer
  #24 = Utf8               testConsumerImpl
  #25 = Utf8               (Ljava/util/function/Consumer;)V
  #26 = Utf8               Signature
  #27 = Utf8               (Ljava/util/function/Consumer<Ljava/lang/Object;>;)V
  #28 = Utf8               lambda$testConsumer$0
  #29 = Utf8               (Ljava/lang/Object;)V
  #30 = Utf8               SourceFile
  #31 = Utf8               LambdaByteCodeAnalysis1.java
  #32 = NameAndType        #17:#18        // "<init>":()V
  #33 = NameAndType        #23:#18        // testConsumer:()V
  #34 = Utf8               BootstrapMethods
  #35 = MethodHandle       #6:#53         // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/Stri
ng;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #36 = MethodType         #29            //  (Ljava/lang/Object;)V
  #37 = MethodHandle       #6:#54         // invokestatic LambdaByteCodeAnalysis1.lambda$testConsumer$0:(Ljava/lang/Object;)V
  #38 = NameAndType        #55:#56        // accept:()Ljava/util/function/Consumer;
  #39 = NameAndType        #24:#25        // testConsumerImpl:(Ljava/util/function/Consumer;)V
  #40 = Class              #57            // java/util/function/Consumer
  #41 = NameAndType        #55:#29        // accept:(Ljava/lang/Object;)V
  #42 = Class              #58            // java/lang/System
  #43 = NameAndType        #59:#60        // out:Ljava/io/PrintStream;
  #44 = Utf8               java/lang/StringBuilder
  #45 = Utf8               Hello, Mr.
  #46 = NameAndType        #61:#62        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #47 = NameAndType        #61:#63        // append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #48 = NameAndType        #64:#65        // toString:()Ljava/lang/String;
  #49 = Class              #66            // java/io/PrintStream
  #50 = NameAndType        #67:#68        // println:(Ljava/lang/String;)V
  #51 = Utf8               LambdaByteCodeAnalysis1
  #52 = Utf8               java/lang/Object
  #53 = Methodref          #69.#70        // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang
/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #54 = Methodref          #15.#71        // LambdaByteCodeAnalysis1.lambda$testConsumer$0:(Ljava/lang/Object;)V
  #55 = Utf8               accept
  #56 = Utf8               ()Ljava/util/function/Consumer;
  #57 = Utf8               java/util/function/Consumer
  #58 = Utf8               java/lang/System
  #59 = Utf8               out
  #60 = Utf8               Ljava/io/PrintStream;
  #61 = Utf8               append
  #62 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #63 = Utf8               (Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #64 = Utf8               toString
  #65 = Utf8               ()Ljava/lang/String;
  #66 = Utf8               java/io/PrintStream
  #67 = Utf8               println
  #68 = Utf8               (Ljava/lang/String;)V
  #69 = Class              #72            // java/lang/invoke/LambdaMetafactory
  #70 = NameAndType        #73:#77        // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invok
e/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #71 = NameAndType        #28:#29        // lambda$testConsumer$0:(Ljava/lang/Object;)V
  #72 = Utf8               java/lang/invoke/LambdaMetafactory
  #73 = Utf8               metafactory
  #74 = Class              #79            // java/lang/invoke/MethodHandles$Lookup
  #75 = Utf8               Lookup
  #76 = Utf8               InnerClasses
  #77 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke
/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #78 = Class              #80            // java/lang/invoke/MethodHandles
  #79 = Utf8               java/lang/invoke/MethodHandles$Lookup
  #80 = Utf8               java/lang/invoke/MethodHandles
{
  public LambdaByteCodeAnalysis1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=1, args_size=1
         0: invokestatic  #2                  // Method testConsumer:()V
         3: return
      LineNumberTable:
        line 6: 0
        line 7: 3
}
SourceFile: "LambdaByteCodeAnalysis1.java"
InnerClasses:
     public static final #75= #74 of #78; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
  0: #35 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljav
a/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #36 (Ljava/lang/Object;)V
      #37 invokestatic LambdaByteCodeAnalysis1.lambda$testConsumer$0:(Ljava/lang/Object;)V
      #36 (Ljava/lang/Object;)V

C:\E_Drive\Projects\SourceCode\Learning\learn\src\com\learn\oracle\LearningJavaLang\ClassesAndObject\LamdaExpression>

LambdaByteCodeAnalysis2.class

C:\E_Drive\Projects\SourceCode\Learning\learn\src\com\learn\oracle\LearningJavaLang\ClassesAndObject\LamdaExpression>javap -v LambdaByteCodeAnalysis2
Classfile /C:/E_Drive/Projects/SourceCode/Learning/learn/src/com/learn/oracle/LearningJavaLang/ClassesAndObject/LamdaExpression/LambdaByteCodeAnalysis2.class
  Last modified 15 Aug, 2018; size 1639 bytes
  MD5 checksum 7e61b6b121ba9d8097f4034f331df1c9
  Compiled from "LambdaByteCodeAnalysis2.java"
public class LambdaByteCodeAnalysis2
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #17.#33        // java/lang/Object."<init>":()V
   #2 = Methodref          #16.#34        // LambdaByteCodeAnalysis2.testConsumer:()V
   #3 = InvokeDynamic      #0:#39         // #0:accept:(I)Ljava/util/function/Consumer;
   #4 = Methodref          #16.#40        // LambdaByteCodeAnalysis2.testConsumerImpl:(Ljava/util/function/Consumer;)V
   #5 = String             #24            // testConsumer
   #6 = InterfaceMethodref #41.#42        // java/util/function/Consumer.accept:(Ljava/lang/Object;)V
   #7 = Fieldref           #43.#44        // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Class              #45            // java/lang/StringBuilder
   #9 = Methodref          #8.#33         // java/lang/StringBuilder."<init>":()V
  #10 = String             #46            // Hello, Mr.
  #11 = Methodref          #8.#47         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #12 = Methodref          #8.#48         // java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #13 = Methodref          #8.#49         // java/lang/StringBuilder.toString:()Ljava/lang/String;
  #14 = Methodref          #50.#51        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #15 = Methodref          #50.#52        // java/io/PrintStream.println:(I)V
  #16 = Class              #53            // LambdaByteCodeAnalysis2
  #17 = Class              #54            // java/lang/Object
  #18 = Utf8               <init>
  #19 = Utf8               ()V
  #20 = Utf8               Code
  #21 = Utf8               LineNumberTable
  #22 = Utf8               main
  #23 = Utf8               ([Ljava/lang/String;)V
  #24 = Utf8               testConsumer
  #25 = Utf8               testConsumerImpl
  #26 = Utf8               (Ljava/util/function/Consumer;)V
  #27 = Utf8               Signature
  #28 = Utf8               (Ljava/util/function/Consumer<Ljava/lang/Object;>;)V
  #29 = Utf8               lambda$testConsumer$0
  #30 = Utf8               (ILjava/lang/Object;)V
  #31 = Utf8               SourceFile
  #32 = Utf8               LambdaByteCodeAnalysis2.java
  #33 = NameAndType        #18:#19        // "<init>":()V
  #34 = NameAndType        #24:#19        // testConsumer:()V
  #35 = Utf8               BootstrapMethods
  #36 = MethodHandle       #6:#55         // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/Stri
ng;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #37 = MethodType         #56            //  (Ljava/lang/Object;)V
  #38 = MethodHandle       #6:#57         // invokestatic LambdaByteCodeAnalysis2.lambda$testConsumer$0:(ILjava/lang/Object;)V
  #39 = NameAndType        #58:#59        // accept:(I)Ljava/util/function/Consumer;
  #40 = NameAndType        #25:#26        // testConsumerImpl:(Ljava/util/function/Consumer;)V
  #41 = Class              #60            // java/util/function/Consumer
  #42 = NameAndType        #58:#56        // accept:(Ljava/lang/Object;)V
  #43 = Class              #61            // java/lang/System
  #44 = NameAndType        #62:#63        // out:Ljava/io/PrintStream;
  #45 = Utf8               java/lang/StringBuilder
  #46 = Utf8               Hello, Mr.
  #47 = NameAndType        #64:#65        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #48 = NameAndType        #64:#66        // append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #49 = NameAndType        #67:#68        // toString:()Ljava/lang/String;
  #50 = Class              #69            // java/io/PrintStream
  #51 = NameAndType        #70:#71        // println:(Ljava/lang/String;)V
  #52 = NameAndType        #70:#72        // println:(I)V
  #53 = Utf8               LambdaByteCodeAnalysis2
  #54 = Utf8               java/lang/Object
  #55 = Methodref          #73.#74        // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang
/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #56 = Utf8               (Ljava/lang/Object;)V
  #57 = Methodref          #16.#75        // LambdaByteCodeAnalysis2.lambda$testConsumer$0:(ILjava/lang/Object;)V
  #58 = Utf8               accept
  #59 = Utf8               (I)Ljava/util/function/Consumer;
  #60 = Utf8               java/util/function/Consumer
  #61 = Utf8               java/lang/System
  #62 = Utf8               out
  #63 = Utf8               Ljava/io/PrintStream;
  #64 = Utf8               append
  #65 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #66 = Utf8               (Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #67 = Utf8               toString
  #68 = Utf8               ()Ljava/lang/String;
  #69 = Utf8               java/io/PrintStream
  #70 = Utf8               println
  #71 = Utf8               (Ljava/lang/String;)V
  #72 = Utf8               (I)V
  #73 = Class              #76            // java/lang/invoke/LambdaMetafactory
  #74 = NameAndType        #77:#81        // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invok
e/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #75 = NameAndType        #29:#30        // lambda$testConsumer$0:(ILjava/lang/Object;)V
  #76 = Utf8               java/lang/invoke/LambdaMetafactory
  #77 = Utf8               metafactory
  #78 = Class              #83            // java/lang/invoke/MethodHandles$Lookup
  #79 = Utf8               Lookup
  #80 = Utf8               InnerClasses
  #81 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke
/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #82 = Class              #84            // java/lang/invoke/MethodHandles
  #83 = Utf8               java/lang/invoke/MethodHandles$Lookup
  #84 = Utf8               java/lang/invoke/MethodHandles
{
  public LambdaByteCodeAnalysis2();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=1, args_size=1
         0: invokestatic  #2                  // Method testConsumer:()V
         3: return
      LineNumberTable:
        line 6: 0
        line 7: 3
}
SourceFile: "LambdaByteCodeAnalysis2.java"
InnerClasses:
     public static final #79= #78 of #82; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
  0: #36 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljav
a/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #37 (Ljava/lang/Object;)V
      #38 invokestatic LambdaByteCodeAnalysis2.lambda$testConsumer$0:(ILjava/lang/Object;)V
      #37 (Ljava/lang/Object;)V

C:\E_Drive\Projects\SourceCode\Learning\learn\src\com\learn\oracle\LearningJavaLang\ClassesAndObject\LamdaExpression>

LambdaByteCodeAnalysis3.class

C:\E_Drive\Projects\SourceCode\Learning\learn\src\com\learn\oracle\LearningJavaLang\ClassesAndObject\LamdaExpression>javap -v LambdaByteCodeAnalysis3
Classfile /C:/E_Drive/Projects/SourceCode/Learning/learn/src/com/learn/oracle/LearningJavaLang/ClassesAndObject/LamdaExpression/LambdaByteCodeAnalysis3.class
  Last modified 15 Aug, 2018; size 1742 bytes
  MD5 checksum 18bf579a4a95e700e29ec7e35bbac1b4
  Compiled from "LambdaByteCodeAnalysis3.java"
public class LambdaByteCodeAnalysis3
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #19.#37        // java/lang/Object."<init>":()V
   #2 = Fieldref           #4.#38         // LambdaByteCodeAnalysis3.testing:I
   #3 = Methodref          #4.#39         // LambdaByteCodeAnalysis3.testConsumer:()V
   #4 = Class              #40            // LambdaByteCodeAnalysis3
   #5 = Methodref          #4.#37         // LambdaByteCodeAnalysis3."<init>":()V
   #6 = InvokeDynamic      #0:#45         // #0:accept:(LLambdaByteCodeAnalysis3;)Ljava/util/function/Consumer;
   #7 = Methodref          #4.#46         // LambdaByteCodeAnalysis3.testConsumerImpl:(Ljava/util/function/Consumer;)V
   #8 = String             #28            // testConsumer
   #9 = InterfaceMethodref #47.#48        // java/util/function/Consumer.accept:(Ljava/lang/Object;)V
  #10 = Fieldref           #49.#50        // java/lang/System.out:Ljava/io/PrintStream;
  #11 = Class              #51            // java/lang/StringBuilder
  #12 = Methodref          #11.#37        // java/lang/StringBuilder."<init>":()V
  #13 = String             #52            // Hello, Mr.
  #14 = Methodref          #11.#53        // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #15 = Methodref          #11.#54        // java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #16 = Methodref          #11.#55        // java/lang/StringBuilder.toString:()Ljava/lang/String;
  #17 = Methodref          #56.#57        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #18 = Methodref          #56.#58        // java/io/PrintStream.println:(I)V
  #19 = Class              #59            // java/lang/Object
  #20 = Utf8               testing
  #21 = Utf8               I
  #22 = Utf8               <init>
  #23 = Utf8               ()V
  #24 = Utf8               Code
  #25 = Utf8               LineNumberTable
  #26 = Utf8               main
  #27 = Utf8               ([Ljava/lang/String;)V
  #28 = Utf8               testConsumer
  #29 = Utf8               testConsumerImpl
  #30 = Utf8               (Ljava/util/function/Consumer;)V
  #31 = Utf8               Signature
  #32 = Utf8               (Ljava/util/function/Consumer<Ljava/lang/Object;>;)V
  #33 = Utf8               lambda$testConsumer$0
  #34 = Utf8               (LLambdaByteCodeAnalysis3;Ljava/lang/Object;)V
  #35 = Utf8               SourceFile
  #36 = Utf8               LambdaByteCodeAnalysis3.java
  #37 = NameAndType        #22:#23        // "<init>":()V
  #38 = NameAndType        #20:#21        // testing:I
  #39 = NameAndType        #28:#23        // testConsumer:()V
  #40 = Utf8               LambdaByteCodeAnalysis3
  #41 = Utf8               BootstrapMethods
  #42 = MethodHandle       #6:#60         // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/Stri
ng;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #43 = MethodType         #61            //  (Ljava/lang/Object;)V
  #44 = MethodHandle       #6:#62         // invokestatic LambdaByteCodeAnalysis3.lambda$testConsumer$0:(LLambdaByteCodeAnalysis3;Ljava/lang/Object;)V
  #45 = NameAndType        #63:#64        // accept:(LLambdaByteCodeAnalysis3;)Ljava/util/function/Consumer;
  #46 = NameAndType        #29:#30        // testConsumerImpl:(Ljava/util/function/Consumer;)V
  #47 = Class              #65            // java/util/function/Consumer
  #48 = NameAndType        #63:#61        // accept:(Ljava/lang/Object;)V
  #49 = Class              #66            // java/lang/System
  #50 = NameAndType        #67:#68        // out:Ljava/io/PrintStream;
  #51 = Utf8               java/lang/StringBuilder
  #52 = Utf8               Hello, Mr.
  #53 = NameAndType        #69:#70        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #54 = NameAndType        #69:#71        // append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #55 = NameAndType        #72:#73        // toString:()Ljava/lang/String;
  #56 = Class              #74            // java/io/PrintStream
  #57 = NameAndType        #75:#76        // println:(Ljava/lang/String;)V
  #58 = NameAndType        #75:#77        // println:(I)V
  #59 = Utf8               java/lang/Object
  #60 = Methodref          #78.#79        // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang
/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #61 = Utf8               (Ljava/lang/Object;)V
  #62 = Methodref          #4.#80         // LambdaByteCodeAnalysis3.lambda$testConsumer$0:(LLambdaByteCodeAnalysis3;Ljava/lang/Object;)V
  #63 = Utf8               accept
  #64 = Utf8               (LLambdaByteCodeAnalysis3;)Ljava/util/function/Consumer;
  #65 = Utf8               java/util/function/Consumer
  #66 = Utf8               java/lang/System
  #67 = Utf8               out
  #68 = Utf8               Ljava/io/PrintStream;
  #69 = Utf8               append
  #70 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #71 = Utf8               (Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #72 = Utf8               toString
  #73 = Utf8               ()Ljava/lang/String;
  #74 = Utf8               java/io/PrintStream
  #75 = Utf8               println
  #76 = Utf8               (Ljava/lang/String;)V
  #77 = Utf8               (I)V
  #78 = Class              #81            // java/lang/invoke/LambdaMetafactory
  #79 = NameAndType        #82:#86        // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invok
e/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #80 = NameAndType        #33:#34        // lambda$testConsumer$0:(LLambdaByteCodeAnalysis3;Ljava/lang/Object;)V
  #81 = Utf8               java/lang/invoke/LambdaMetafactory
  #82 = Utf8               metafactory
  #83 = Class              #88            // java/lang/invoke/MethodHandles$Lookup
  #84 = Utf8               Lookup
  #85 = Utf8               InnerClasses
  #86 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke
/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  #87 = Class              #89            // java/lang/invoke/MethodHandles
  #88 = Utf8               java/lang/invoke/MethodHandles$Lookup
  #89 = Utf8               java/lang/invoke/MethodHandles
{
  int testing;
    descriptor: I
    flags:

  public LambdaByteCodeAnalysis3();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_0
         6: putfield      #2                  // Field testing:I
         9: return
      LineNumberTable:
        line 3: 0
        line 5: 4

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=1, args_size=1
         0: invokestatic  #3                  // Method testConsumer:()V
         3: return
      LineNumberTable:
        line 8: 0
        line 9: 3
}
SourceFile: "LambdaByteCodeAnalysis3.java"
InnerClasses:
     public static final #84= #83 of #87; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
  0: #42 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljav
a/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #43 (Ljava/lang/Object;)V
      #44 invokestatic LambdaByteCodeAnalysis3.lambda$testConsumer$0:(LLambdaByteCodeAnalysis3;Ljava/lang/Object;)V
      #43 (Ljava/lang/Object;)V

C:\E_Drive\Projects\SourceCode\Learning\learn\src\com\learn\oracle\LearningJavaLang\ClassesAndObject\LamdaExpression>

person pjj    schedule 13.08.2018    source источник
comment
Создание Lambda из статического контекста (внутри статического метода) приведет к созданию класса, который не имеет контекста this.   -  person Marcos Vasconcelos    schedule 13.08.2018


Ответы (2)


Спецификация языка Java говорит следующее:

В отличие от кода, появляющегося в объявлениях анонимных классов, значение имен и ключевых слов this и super, появляющихся в теле лямбда, наряду с доступностью объявлений, на которые ссылаются, такие же, как и в окружающем контексте (за исключением того, что параметры лямбда вводят новые имена).

Прозрачность this (как явной, так и неявной) в теле лямбда-выражения, то есть обработка его так же, как и в окружающем контексте, обеспечивает большую гибкость для реализаций и предотвращает зависимость значения неполных имен в теле. по разрешению перегрузки.

С практической точки зрения, для лямбда-выражения необычно говорить о себе (либо для рекурсивного вызова самого себя, либо для вызова других своих методов), в то время как более распространено желание использовать имена для ссылки на вещи в охватывающем классе, которые были бы в противном случае будет затенен (this, toString()). Если необходимо, чтобы лямбда-выражение ссылалось на себя (как если бы через this), вместо этого следует использовать ссылку на метод или анонимный внутренний класс.

person Johannes Kuhn    schedule 13.08.2018
comment
Пожалуйста, поправьте меня за мой первый вопрос, что объект будет создан для лямбда-выражения - но будет ли каждый раз создаваться новый объект, это зависит, верно? - person pjj; 13.08.2018
comment
Что ж, если создается новый объект, зависит от реализации лямбда-фабрики. - person Johannes Kuhn; 13.08.2018
comment
@ это легко проверить - напишите лямбду с захватом и лямбду без захвата и посмотрите сгенерированные классы... - person Eugene; 13.08.2018
comment
@Eugene Евгений, может быть, вы хотите подробно изложить свой ответ? - person pjj; 13.08.2018
comment
@pjj нет, это присутствовало на SO 100%, просто найдите его. Создаст ли лямбда экземпляр в куче... самый первый результат - person Eugene; 13.08.2018
comment
@Eugene: хорошо, спасибо за указатель - person pjj; 13.08.2018
comment
Сгенерированные классы идентичны. Сначала лямбда-выражение преобразуется в (приватный) метод, а на старое место помещается вызов invokedynamic. Аргументами для динамического вызова являются захваченные переменные. - person Johannes Kuhn; 14.08.2018
comment
@Eugene Я искал заголовок stackoverflow.com/questions/27524445/, и это не отвечает на мой вопрос (наряду с анализом байт-кода), будет ли генерироваться объект или не. - person pjj; 14.08.2018
comment
@Eugene Итак, я создал свои собственные классы и попробовал кое-что с анализом байт-кода, но я не могу разобраться в этом ... если у вас мало времени, не могли бы вы помочь ... Я обновил свой код и байт-код в своем вопросе ... - person pjj; 14.08.2018
comment
@JohannesKuhn Я сгенерировал байт-код и не вижу инструкции dynamicinvocation ... если у вас мало времени, не могли бы вы помочь разобраться во всем ... - person pjj; 14.08.2018
comment
@JohannesKuhn Я даже не могу понять новый метод, о котором вы говорили, который будет иметь код лямбда-выражения - person pjj; 14.08.2018
comment
@pjj stackoverflow.com/a/45393978/1059372 - person Eugene; 14.08.2018
comment
@Eugene Хорошо, спасибо, позвольте мне пройти через это. - person pjj; 14.08.2018
comment
@Eugene Я думаю, что я что-то упускаю, я не вижу инструкции динамического вызова в моем байт-коде, что-то вроде этого 20: invokedynamic #11, 0, который есть в этом ответе ... Думаю, я что-то упустил .... Я сгенерировал байт-код как javap -v ........ ... Я думаю, что это мое незнание байт-кода, что я не могу понять вещи... - person pjj; 15.08.2018
comment
@pjj, вероятно, тоже javap -c -p .. но если вы не можете читать байт-код, это будет трудно понять - person Eugene; 15.08.2018
comment
@Eugene Спасибо, я сгенерировал эти аргументы, и на этот раз байт-код выглядел намного проще, и я мог понять несколько вещей. Я мог видеть, что если в LE используется локальная переменная, то метод начальной загрузки захватил эти переменные, и если переменные экземпляра используются LE и LE захватили экземпляр класса.. однако, если не смогли понять и детерминировано увидеть, что объект создан для лямбда-выражения.... - person pjj; 15.08.2018
comment
Настоящая магия происходит в java.lang.invoke.MetaLambdaFactory. Инструкция invokedynamic вызывает метод начальной загрузки при первом вызове, а метод начальной загрузки возвращает CallSite. Наивная реализация создала бы (анонимный) класс и использовала бы MethodHandle конструктора для сайта вызова. Но если вы знаете, что конструктор не принимает никаких аргументов, вы также можете вернуть дескриптор константного метода. - person Johannes Kuhn; 15.08.2018
comment
@JohannesKuhn Хорошо, большое спасибо за ваш вклад. У меня есть еще вопросы о внутренней работе LE, поэтому я задам еще один вопрос. - person pjj; 17.08.2018

Мой ответ и простая логика будут заключаться в том, что, поскольку this используется для ссылки на состояние объекта, а лямбда-выражения не имеют никакого состояния (доступ к внешней переменной также фиксируется), поэтому нет смысла иметь this ссылку на объект лямбда-выражение.

person hagrawal    schedule 13.08.2018