javac数据流分析的奇怪误报

发布于 2025-01-01 12:52:47 字数 1407 浏览 0 评论 0原文

我有以下形式的代码:

class Test {
  private final A t;

  public Test() {

    for ( ... : ... ) {
      final A u = null;
    }

    t = new A();
  }

  private class A {}
}

编译器说:

variable t might already have been assigned

有趣的是,如果我对循环执行以下任何更改,它就会起作用!

  • 将循环的内容更改为 A u = null
  • 删除循环(但保留 final A u = null;
  • 将 foreach 样式的循环替换为经典的计数

循环在这里?

注意:我无法获得导致错误的最小示例,因此“环境”(大约 1400 loc)可能有问题。不过,我看不出什么会干扰 t 的初始化,因为 t 没有写入其他地方。

有趣的事实:如果我删除它,IntelliJ IDEA 会说“变量 'u' 可以有 'final' 修饰符...”。

我使用javac 1.6.0_26。

更新:就是这样,这个示例非常如此

import java.util.List;

class A {
  private final boolean a;

  public A() {
    for ( final Object o : new Object[] {} ) {
      final Object sh = null;
    }

    a = true;
  }

  class B {
    private final Object b1;
    private final Object b2;

    B() {
      b1 = null;
      b2 = null;
    }
  }
}

无法在 javac 1.6.0_26 上编译,但可以在 javac 1.7 上编译。 0_02。所以我想我遇到了一些邪恶的极端情况......什么?

删除 final 中的任何操作,

  • 执行删除任何一个成员
  • 请注意,您可以在 A() 中的循环内
  • 将循环替换为普通的 for 循环,例如 for ( int i=0; i<100; i++ ) { ... }

它将编译。

I have code of the following form:

class Test {
  private final A t;

  public Test() {

    for ( ... : ... ) {
      final A u = null;
    }

    t = new A();
  }

  private class A {}
}

Compiler says:

variable t might already have been assigned

Interestingly, if I perform any of the following changes to the loop it works out!

  • Change the loop's content to A u = null
  • Remove the loop (but keep final A u = null;)
  • Replace the foreach-style loop with a classic counting loop

What is going on here?

Note: I could not get the minimal example to cause the error so there is probably something wrong with the "environment" (about 1400 loc). I can not see what could disturb the initialisation of t, though, as t is written to nowhere else.

Fun fact: IntelliJ IDEA says "Variable 'u' can have 'final' modifier..." if I remove it.

I use javac 1.6.0_26.

Update: There you go, this example so so minimal:

import java.util.List;

class A {
  private final boolean a;

  public A() {
    for ( final Object o : new Object[] {} ) {
      final Object sh = null;
    }

    a = true;
  }

  class B {
    private final Object b1;
    private final Object b2;

    B() {
      b1 = null;
      b2 = null;
    }
  }
}

Fails to compile on javac 1.6.0_26 but compiles on javac 1.7.0_02. So I guess I hit some wicked corner case of ... something?

Note that you can do any of

  • Remove any one member
  • Remove final inside the loop in A()
  • Replace the loop with a normal for loop, e.g. for ( int i=0; i<100; i++ ) { ... }

and it will compile.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

奶茶白久 2025-01-08 12:52:47

如果你有很多代码我会尝试这个。

private final A t;

public Test() {
    final int t = 1;

   for ( ... ) {
      final A u = null;
   }

   this.t = new A();

这将导致任何“可能”初始化 t 的代码失败(并显示在编译器中)。

If you have lots of code I would try this.

private final A t;

public Test() {
    final int t = 1;

   for ( ... ) {
      final A u = null;
   }

   this.t = new A();

This will cause any code which "might" initialise t to fail (and show up in the compiler.

永言不败 2025-01-08 12:52:47

如果您的构造函数碰巧调用了另一个本身未设置 t 的构造函数,则编译器将无法理解这一点。

请参阅此处

If you're constructor happen to call another constructor that doesn't itself set t, the compiler fails to understand that.

See here.

影子的影子 2025-01-08 12:52:47

由于该问题在 Java 7 中已得到解决,因此它可能是 Java 6 编译器中的一个错误。

As the problem is fixed in Java 7, it is probably a bug in the Java 6 compiler.

撑一把青伞 2025-01-08 12:52:47

据我了解,将对象存储在最终变量中并不会使您的对象不可变,而是使其引用不可变。这就解释了为什么当您删除final关键字时它会起作用,并且根据删除for循环,我认为您正在访问对象引用而不是实例。

It is my understanding that storing an object in a final var does not make your object immutable but its reference. That explain why when you remove the final keyword it works and as per removing the for-loop, i think you are accessing the object reference and not an instance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文