Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

423
Views
Effective final vs final in Java 8

I am executing below in main method:

int secrete = 42;
for (int i = 0; i < 5; i++) {
    Consumer<String> myprinter2 =
                    msg -> {
                        System.out.println("consuming " + msg + " ," + secrete);
                    };
     myprinter2.accept(myprinter2.toString());
}

The output for the above code is:

consuming Main$$Lambda$1/1324119927@6d311334 ,42
consuming Main$$Lambda$1/1324119927@682a0b20 ,42
consuming Main$$Lambda$1/1324119927@3d075dc0 ,42
consuming Main$$Lambda$1/1324119927@214c265e ,42
consuming Main$$Lambda$1/1324119927@448139f0 ,42

If I change secrete to be final, then the output is:

consuming Main$$Lambda$1/2003749087@41629346 ,42
consuming Main$$Lambda$1/2003749087@41629346 ,42
consuming Main$$Lambda$1/2003749087@41629346 ,42
consuming Main$$Lambda$1/2003749087@41629346 ,42
consuming Main$$Lambda$1/2003749087@41629346 ,42

secrete is effectively final even if I do not declare it final, so why is each lambda considered a new object when I do not declare it final?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

"Effectively final" is not technically required, it could've been done without. But the language designers put this restriction to avoid confusion, because if the variable kept changing, what value would the lambda see, the initial, or the latest? Other languages that have lambda don't have this restriction, and the spec sets the expectation for this use case.

Given the following code:

import java.util.function.Consumer;


class Main {  
  public static void main(String args[]) { 
    int i = 42;
    final int j = 41;
    for (int k = 0; k < 5; k++) {
      Consumer<String> x = msg -> System.out.printf("x=%s, i=%d%n", msg, i);
      Consumer<String> y = msg -> System.out.printf("y=%s, j=%d%n", msg, j);
      Consumer<String> z = msg -> System.out.printf("z=%s%n", msg);
      x.accept(x.toString());
      y.accept(y.toString());
      z.accept(z.toString());
    }
  } 
}

When we inspect the generated bytecode with javap -c -v Main.class, we see:

11: invokedynamic #7,  0              // InvokeDynamic #0:accept:(I)Ljava/util/function/Consumer;
16: astore_3
17: invokedynamic #11,  0             // InvokeDynamic #1:accept:()Ljava/util/function/Consumer;
22: astore        4
24: invokedynamic #14,  0             // InvokeDynamic #2:accept:()Ljava/util/function/Consumer;

We can see how the lambdas are translated. The corresponding static methods show that the first lambda is a capturing lambda and has an integer 1st parameter (#71) after translation, while the other ones don't.

BootstrapMethods:
  0: #63 REF_invokeStatic 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;
    Method arguments:
      #70 (Ljava/lang/Object;)V
      #71 REF_invokeStatic Main.lambda$main$0:(ILjava/lang/String;)V
      #74 (Ljava/lang/String;)V
  1: #63 REF_invokeStatic 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;
    Method arguments:
      #70 (Ljava/lang/Object;)V
      #75 REF_invokeStatic Main.lambda$main$1:(Ljava/lang/String;)V
      #74 (Ljava/lang/String;)V
  2: #63 REF_invokeStatic 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;
    Method arguments:
      #70 (Ljava/lang/Object;)V
      #78 REF_invokeStatic Main.lambda$main$2:(Ljava/lang/String;)V
      #74 (Ljava/lang/String;)V

So, it's just how lambdas are translated. You can find more details in this article.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!