栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Lambda的行为与匿名内部类不同

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Lambda的行为与匿名内部类不同

根据生成的字节码:

Java(TM)SE运行时环境(内部版本1.8.0-b132)

Lambda:

 private static java.lang.Integer lambda$main$0(java.lang.Integer);   descriptor: (Ljava/lang/Integer;)Ljava/lang/Integer;   flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC   Code:     stack=2, locals=2, args_size=1        0: aload_0        1: invokevirtual #9       // Method java/lang/Integer.intValue:()I        4: iconst_1        5: iadd        6: invokestatic  #6       // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;        9: dup       10: astore_0       11: astore_1       12: aload_0       13: areturn     LineNumberTable:       line 20: 0     LocalVariableTable:       Start  Length  Slot  Name   Signature0      14     0     t   Ljava/lang/Integer;

匿名类:

  public java.lang.Integer get(java.lang.Integer);    descriptor: (Ljava/lang/Integer;)Ljava/lang/Integer;    flags: ACC_PUBLIC    Code:      stack=2, locals=4, args_size=2         0: aload_1         1: astore_2         2: aload_1         3: invokevirtual #2       // Method java/lang/Integer.intValue:()I         6: iconst_1         7: iadd         8: invokestatic  #3       // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;        11: dup        12: astore_1        13: astore_3        14: aload_2        15: areturn      LineNumberTable:        line 16: 0      LocalVariableTable:        Start  Length  Slot  Name   Signature 0      16     0  this   LTest$1; 0      16     1     t   Ljava/lang/Integer;

如您所见,在匿名类中,从本地变量表(方法参数 t )加载变量后,运行时将参数的副本存储在另一个变量( astore_2
)中,然后使用该参数副本作为返回值。

Lambda方法不会复制参数(加载->取消装箱->添加1->框->存储->加载->返回)。

更新

绝对是javac错误。

我来自http://hg.openjdk.java.net/jdk8u/jdk8u

匿名类和lambda转换为以下中间表示形式:

@Override()public Integer get(Integer t) {    return (let  final Integer $112619572 = t in        (let  final Integer $1295226194 = t = Integer.valueOf((int)(t.intValue() + 1)) in $112619572));} private static Integer lambda$main$0(final Integer t) {    return (let  final Integer $1146147158 = t = Integer.valueOf((int)(t.intValue() + 1)) in t);}

在lambda中,生成的方法参数标记为final,因为LambdaToMethod转换器将所有参数标记为FINAL(根据源代码
LambdaTranslationContext.translate(…):1899 )。

然后让表达式生成器检查变量标志,以及是否在最终变量时忽略临时变量生成(根据源代码 Lower.abstractRval(…):2277
),因为认为禁止进行修改。

可能的解决方案:

  1. 禁止在lambda或
  2. 从lamda生成的方法中的局部变量( LambdaTranslationContext.translate(…):1894 )和参数( LambdaTranslationContext.translate(…):1899 )中删除FINAL标志:

     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);

我删除了FINAL标志,并从以下网址获得了预期的测试结果:https
:
//bugs.openjdk.java.net/browse/JDK-8038420



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/414416.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号