【问题标题】:How to use IntelliJ's Evaluate Expression tool with lambdas and outer scopes?如何将 IntelliJ 的 Evaluate Expression 工具与 lambdas 和外部范围一起使用?
【发布时间】:2015-01-22 18:33:50
【问题描述】:

这是一个简单的 Java 8 lambda 示例。

public class Main {
    public static void main(String[] args){
        String outerScope = "outer";
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                String runnableInner = "runnable inner";
                System.out.println("inside runnable: " + outerScope);
                Void avoid = null; //Breakpoint
            }
        };
        Runnable lambda = () -> {
            String lambdaInner = "lambda inner";
            System.out.println("inside lambda: " + outerScope);
            Void avoid = null; //Breakpoint
        };
        runnable.run();
        lambda.run();
    }
}

runnable 范围内,可以使用 IntelliJ 的“评估表达式”工具来评估 outerScope 的定义。

但是,在lambda 范围内,outerScope 是未定义的。

两个打印语句都正确打印了outerscope 的值。

有没有办法解决这个问题?

【问题讨论】:

标签: java intellij-idea lambda java-8


【解决方案1】:

Lambda 表达式被编译成所属类中的合成方法。当我在您的班级中运行javap -private -l 时,此方法打印为:

private static void lambda$main$0(java.lang.String);
  LineNumberTable:
    line 18: 0
    line 19: 3
    line 20: 28
    line 21: 30
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
        3      28     1 lambdaInner   Ljava/lang/String;
       30       1     2 avoid   Ljava/lang/Void;

您在这里可以看到,该方法有一个参数,该参数将接收outerScope 变量的实际捕获值。但是LocalVariableTable 没有为其声明名称,这很可能是调试器不显示其运行时值的原因。

具有讽刺意味的是,这意味着如果我们删除LocalVariableTable 属性,我们将看到所需的值。例如。当使用 -g:lines 编译并在 lambda 表达式主体内的断点处停止时,Netbeans 调试器显示:

args    String  "outer"
Variable information not available, source compiled without -g option           

所以我们知道看到所有作为参数传递的值,代价是看不到方法内声明的其他局部变量。


所以需要的是一个 LocalVariableTable 属性,其中包含捕获值的外部作用域的变量名称,这个问题必须在 javac 中解决,这将是 apparently happen in jdk1.8u60

如果您迫不及待并且不想编写修补LocalVariableTable 属性的工具,您可以认为合成方法的调用者 知道参数值。因此,如果您在堆栈跟踪中向上一步到运行时生成的 lambda 实例,您将看到所有捕获的值作为实例变量,尽管它们将生成像 arg$1 等的名称。

【讨论】:

    猜你喜欢
    • 2021-06-09
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多