【问题标题】:Different compilation error when final local variable is used with while loop最终局部变量与 while 循环一起使用时出现不同的编译错误
【发布时间】:2014-08-24 10:46:01
【问题描述】:

示例代码:

编译错误:

可能已经分配了最终的局部变量标志

final boolean flag;
while (flag = false) { // I am using = instead of == just to test it
    System.out.println("inside loop");
}

编译错误:

无法访问的代码

final boolean flag = false;
while (flag) {
    System.out.println("inside loop");
}

我知道:

  • 局部变量必须在首次使用前进行初始化。
  • 根据编码标准,最终局部变量必须在声明时进行初始化。

问题:

  • 这些语句之间有什么区别?据我了解,两者都是一样的。
  • 为什么第一个示例代码不涉及无法访问的代码。第二个编译错误我很清楚。

如果在 if 条件下工作正常

final boolean flag;
if (flag = false) { // no compilation error
    System.out.println("inside if block");
}

如果我在while 循环中添加一个break 语句,以确保编译器可以在其生命周期内只初始化一个final 局部变量,那么如果工作正常。

final boolean flag;
while (flag = false) {
    System.out.println("inside if block");
    break;
}

【问题讨论】:

  • 对于您的最后一种情况,它有效,因为尚未分配标志。如果你把第一行改成final boolean flag = false就不行了
  • @Chip 是的,我知道,无法再次为 final 变量赋值。
  • 所以最后得出的结论是:我们不能在循环内分配最终变量。感谢大家宝贵的时间。
  • @Chip 如果我们添加 break 语句,我们可以。
  • 是的,我说谢谢大家。

标签: java if-statement while-loop final


【解决方案1】:

案例 1: 每次在“while”循环中迭代时都会分配“flag”。您使用的是赋值运算符 '=' 而不是 '=='。

案例 2: 'flag' 始终为 false,因此 'if' 中的代码永远不会执行。

【讨论】:

  • 编译器在编译时知道final变量的值,那么为什么它不谈论无法访问的代码。
  • 因为 'flag = false' 是一个赋值,不返回布尔值,而 'if' 语句需要一个布尔值。
  • 赋值语句在java中返回赋值
  • @user3218114 您只能为最终变量赋值一次。这就是您在 while 循环中的分配失败的原因
  • 编译器分多个阶段工作。检查无法访问代码的阶段比分配检查晚。通常在编译器中,一旦检测到错误,它就不会继续下一个阶段。一般来说,这会减少错误数量并帮助您更快地解决编译错误。
【解决方案2】:

这些陈述之间有什么区别?根据我的 理解两者是一样的。

你的代码怎么会一样???在您的第一种情况下,您将 flag 变量初始化为 false,因此它将假设循环的每次迭代都会初始化 flag 变量(编译器在编译时做出的决定,因为它不知道 no . of 迭代),但实际上此代码永远不会被执行---因此将其视为非最终变量,因此是矛盾的,而在第二种情况下它也不会运行由于该标志仅在声明步骤中已被声明为 false,NOT INSIDE THE BODY OF LOOP!!!所以,第二个将是一个无限循环!

final boolean flag;
while (flag = false) {                   // First code---flag final variable initialised with each iteration
System.out.println("inside loop");
}

final boolean flag = false;
while (flag) {                          //  Second code
System.out.println("inside loop");
}

为什么第一个示例代码没有讨论无法访问的代码。第二 我很清楚编译错误。

因为先报任何一个编译错误。在这种情况下,第一个显示与flag 变量错误声明相关的错误。取自Wikipedia

最终变量只能初始化一次,或者通过 初始化程序或赋值语句。它不需要是 在声明点初始化:这被称为“空白 final" 变量。一个类的空白 final 实例变量必须是 在它所在的类的每个构造函数中明确分配 宣布;同样,一个空白的 final 静态变量肯定是 在声明它的类的静态初始化器中赋值;

【讨论】:

  • 第一个显示与标志变量错误声明有关的错误这是什么意思?它在哪里被错误地声明了?
  • 查看我最后一段取自维基百科!
  • 您正在使用 instance 空白 final 变量。我说的是local final 变量。
  • 不,@user3218114-您的第一个循环也是一个无限循环,在这种情况下,flag 作为最终变量总是在每个循环的迭代中被初始化---从而引发编译错误这怎么可能!
  • 为什么是无限循环?我已经将它初始化为false 循环内的代码永远不会到达。
【解决方案3】:

从 cmets 看来,您似乎正在寻找为什么第一个代码确实会为您提供 The final local variable flag may already have been assigned 而不是 Unreachable error

这是因为这里详细介绍了 java 编译的各个阶段:http://openjdk.java.net/groups/compiler/doc/compilation-overview/

表达式在第一阶段进行评估 (Attr )。只有在第一阶段没有错误时才进行流分析。由于第一阶段发现非法赋值,第二阶段(Flow)不会被执行,你也不会得到Unreachable Error

【讨论】:

  • 答案是final 变量应该只初始化一次。如果是while(没有break 语句),编译器会说可能已经分配了最终的局部变量标志,因为它可能会在下一次迭代中回到条件。
猜你喜欢
  • 2014-01-23
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 2012-03-03
  • 1970-01-01
相关资源
最近更新 更多