当前位置: 首页 > 面试题库 >

匿名类中的“变量示例可能尚未初始化”

法池暝
2023-03-14
问题内容

这个 自我回答的问题是由于变量“snackbar”可能尚未初始化而引起的。我认为还有更多细节,最好与该特定问题分开添加。

为什么以下代码无法编译?

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并查看匿名类的接口:

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中的字符串是不可变的,因此您无法编辑字符串,因此应更改方法。 我将您的代码更改为类似的内容,但是我认为您的编辑方法应该做另一件事

  • 所以我已经在结果中声明了相关字符串的值,但是它仍然说我的变量“result”可能还没有初始化。 我正在尝试实现与此类似的输出。任何人都可以帮我吗?谢谢!

  • 我正在研究Euler Problem 9项目,其中说明: 毕达哥拉斯三元组是由三个自然数组成的集合 例如,3^2 4^2=9 16=25=52。 确实存在一个毕达哥拉斯三重态,其bc=1000。查找产品abc。 以下是我到目前为止所做的: 当我运行代码时,会出现以下错误: 注意:我的每个变量(a、b和c)都有不同的行号。 我想当我声明a、b和c为整数时,如果不赋值,默认值是0。 即使不是这样,在我

  • 问题内容: 我得到错误: TestCounter.java:115:变量计数器可能尚未初始化counters [i] = new Counter(i); 而且我不知道如何解决它。我知道我的课程“” 有效。下面是我的代码,如果您可以看一下,我将非常高兴。此代码包装在类的main方法中。 问题答案: 您尚未创建数组,只是声明了变量。 您需要这样做: 或类似的东西

  • 在最后一行显示为时出错 :::: 变量结果可能尚未初始化 这是我的代码:

  • 我试图使用Android Studio中的Google Firebase(机器学习工具包)的例子。将图像变量传递到检测器时出错。processImage方法(错误如下所示)。 我怎样才能克服这个错误?我必须使用FirebaseVisionImage。try-catch块中的fromFilePath,但错误消息告诉我image变量可能未初始化。 错误:变量映像可能尚未初始化