Lambda behaving differently than anonymous inner class

Ivan Babanin babanin at gmail.com
Wed Mar 26 21:22:18 UTC 2014


It's definitely a javac bug.

Anonymous class and lambda converts to following intermediate
representations:

@Override()
public Integer get(Integer t) {
    return (let /*synthetic*/ final Integer $112619572 = t in 
       (let /*synthetic*/ final Integer $1295226194 = t =
Integer.valueOf((int)(t.intValue() + 1)) in $112619572));
}

/*synthetic*/ private static Integer lambda$main$0(final Integer t) {
    return (let /*synthetic*/ final Integer $1146147158 = t =
Integer.valueOf((int)(t.intValue() + 1)) in t);
}

In lambda generated method parameter marked as final, because LambdaToMethod
translator 
marks all parameters as FINAL (according source code
LambdaTranslationContext.translate(.) : 1899).

Then let expression builder checks variable flags and when if it's final
omits temporary variable generation
(according source code Lower. abstractRval(.) : 2277), because modification
considered to be prohibited.

Possible solutions:
1) Forbid parameter modification inside lambda or
2) Remove FINAL flag from local variable
(LambdaTranslationContext.translate(.) : 1894)
   and parameter (LambdaTranslationContext.translate(.) : 1899) in lamda
generated method:
 
     case LOCAL_VAR:
       ret = new VarSymbol(FINAL, name, types.erasure(sym.type),
translatedSym);
     ...
     
     case PARAM:
       ret = new VarSymbol(FINAL | PARAMETER, name, types.erasure(sym.type),
translatedSym);
     ...

I removed FINAL flag and got expected results on tests from:
https://bugs.openjdk.java.net/browse/JDK-8038420

sy,
Ivan



More information about the lambda-dev mailing list