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