if语句没有花括号的奇怪编译错误

5
以下 Java 代码会抛出编译器错误:
if ( checkGameTitle(currGame) )
    ArrayList<String> items = parseColumns( tRows.get(rowOffset+1), currGame, time, method );

checkGameTitle是一个公共静态函数,返回布尔值。所有的错误都是类型为“无法找到符号”,符号是变量ArrayList变量String变量items

但是,如果我添加{花括号},那么代码会编译而没有任何错误。这可能是为什么?没有它们,if子句存在一些歧义吗?

6个回答

11
如果在这个位置声明变量items,它将无法从任何地方访问。因此,允许这种构造毫无意义。
另一方面,当你打开一个代码块时,最初做同样的事情仍然没有意义。但是可以预期,您将希望稍后扩展该代码块,并且它最终会有意义。

5
+1 - Java的语法避免了编程错误。 参考链接:http://java.sun.com/docs/books/jls/second_edition/html/syntax.doc.html 这突显了像Java这样定义良好的语法的重要性。 - Tim Bender

4

使用花括号,你可以创建一个包含声明的代码块。如果没有花括号,你只能有一个语句,而不是一个声明,就像你的例子一样。


2
我认为在这种情况下,Java语言规范中的相关部分总是有帮助的,可以参考§14.4

每个局部变量声明语句都立即包含在一个块中。局部变量声明语句可以自由地与块中其他类型的语句混合使用。

换句话说,局部变量声明只能作为独立的声明出现在块({})的下一级。它们不被视为Statements(§14.5),后者是跟在if (....)之后的东西。


1

问题在于这个:

if ( condition )
    ArrayList<String> items = ...;

...本质上等同于这个:

if ( condition ) {
    ArrayList<String> items = ...;
}

你已经定义并初始化了items,但是当你退出语句/块时,它立即超出了作用域,因此你实际上不能将其用于任何事情。编译器正在警告你。


0
编译器错误是因为语言规则没有明确指出“items”变量声明的范围。
例如,如果我有这样一段代码块:
bool isTrue() {
  bool returnValue = false;
  if (cheese.isGreen()) {
    returnValue = true;
  }
  return returnValue;
}

很明显,returnValue 是整个方法中一个有效的变量。

如果我有这样一段代码:

bool isTrue() {
  if (cheese.isGreen()) {
    bool returnValue = true;
  }
  return returnValue;
}

很明显,returnValue在“if语句”之外是无效的。

但如果我有这样一段代码:

bool isTrue() {
  if (cheese.isGreen())
    bool returnValue = true;
  return returnValue;
}

不清楚returnValue是在if语句的范围内还是在整个方法的范围内。这是由于Java语言语法布局的细节所致。基本上,允许在任何块中声明新变量(因为块明确定义了变量的作用域),但是此if语句没有包含块。

如果您假设Java会默默地为您添加块,则作用域位于“遗忘的块”内。如果您认为由于没有显式块来包含作用域,因此变量的作用域与方法的其余部分处于同一级别,则存在各种争论,以确定哪种观点更“正确”,因此整个尝试这样做是被禁止的。

如果您觉得这很奇怪,并且认为只有疯子才不会假定变量在暗示的块的范围内定义,请记住,在Java之前存在着作用域将与返回语句处于同一级别的语言。是的,按今天的标准看来是疯狂的语言,但它们仍然存在。


0

你正在if语句中定义变量items,因此它将无法在该范围之外的任何地方使用。

编辑:太慢了...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接