gpt4 book ai didi

java - 匿名类中的 "Variable example might not have been initialized"

转载 作者:搜寻专家 更新时间:2023-11-01 01:16:02 24 4
gpt4 key购买 nike

self-answered question灵感来自 Variable 'snackbar' might not have been initialized .我觉得有更多细节可以更好地与该特定问题分开添加。

为什么下面的代码不能编译?

public class Example {
public static void main(String[] args) {
final Runnable example = new Runnable() {
@Override
public void run() {
System.out.println(example); // Error on this line
}
};
}
}

编译错误:

error: variable example might not have been initialized

最佳答案

发生这种情况是因为匿名类的实现方式。如果您对代码稍作更改然后反编译,您可以看到这一点:

    final Runnable other = null;
final Runnable example = new Runnable() {
@Override
public void run() {
System.out.println(other);
}
};

即使匿名类引用不同的局部变量。现在将编译;我们可以使用javap反编译,看到匿名类的接口(interface):

final class Example$1 implements java.lang.Runnable {
final java.lang.Runnable val$other;
Example$1(java.lang.Runnable);
public void run();
}

(Example$1 是 Java 内部引用匿名类的名称)。

这表明编译器已经为匿名类添加了一个构造函数,该类接受一个Runnable参数;它还有一个名为 val$other 的字段。此字段的名称应暗示此字段与 other 局部变量相关。

你可以深入挖掘字节码,看到这个参数被分配给了val$other:

  Example$1(java.lang.Runnable);
Code:
0: aload_0
// This gets the parameter...
1: aload_1
// ...and this assigns it to the field val$other
2: putfield #1 // Field val$other:Ljava/lang/Runnable;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."<init>":()V
9: return

因此,这表明匿名类从其封闭范围访问变量的方式:它们只是在构造时传递值。

这应该有望说明为什么编译器会阻止您编写问题中的代码:它需要能够将对 Runnable 的引用传递给匿名类才能构造它.但是,Java 评估以下代码的方式:

final Runnable example = new Runnable() { ... }

是先对右边进行全求值,然后赋值给左边的变量。但是,它需要右侧变量的值才能传递到 Runnable$1 的生成构造函数中:

final Runnable example = new Example$1(example);

之前未声明的example 不是问题,因为这段代码在语义上等同于:

final Runnable example;
example = new Example$1(example);

所以你得到的错误不是变量无法解析 - 但是,example 在用作构造函数的参数之前没有被赋值,因此编译器错误。


有人可能会争辩说这只是一个实现细节:必须将参数传递给构造函数应该无关紧要,因为 run() 方法无法做到这一点在分配之前被调用。

实际上,这不是真的:您可以在赋值之前调用 run(),如下所示:

final Runnable example = new Runnable() {
Runnable runAndReturn() {
run();
return this;
}

@Override public void run() {
System.out.println(example);
}
}.runAndReturn();

如果允许在匿名类中引用example,您就可以这样写。因此,不允许引用该变量。

关于java - 匿名类中的 "Variable example might not have been initialized",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35204884/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com