不带大括号的 if 子句出现奇怪的编译器错误
以下 Java 代码引发编译器错误:
if ( checkGameTitle(currGame) )
ArrayList<String> items = parseColumns( tRows.get(rowOffset+1), currGame, time, method );
checkGameTitle
是一个公共静态函数,返回一个布尔值。这些错误都是“找不到符号”类型,符号为variable ArrayList
、variable String
和variable items
。
但是,如果我添加{花括号},则代码编译时不会出现错误。为什么会这样?没有它们的 if
子句是否存在歧义?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果此时声明一个变量
items
,则无法从任何地方访问它。因此,允许这种构造是没有意义的。OTOH,当你打开一个块时,做同样的事情(一开始)仍然没有意义。但预计您稍后会想要扩展该块,并且它最终会有意义。
If you declare a variable
items
at this point, it's not accessible from anywhere. So it would make no sense to allow this construct.OTOH, when you open a block, it still makes no sense to do the same thing (at first). But it's expected, that you'll want to extend the block later, and that it will eventually make sense.
使用花括号,您可以创建一个可以包含声明的块。如果没有大括号,则只能有语句,不能有声明,例如您的示例
With curly braces, you create a block that can contain declarations. Without the braces, you can only have a statement, not a declaration, such as your example
正因为我认为它在这些情况下总是有帮助的,所以这里 Java 语言规范的相关部分是 §14.4:
换句话说,局部变量声明只能作为独立声明出现在紧邻块“下方”的级别 (
{}
)。它们不被视为语句
(§14.5),它们是在if (....)
之后的内容。Just because I think it's always helpful in these situations, the relevant part of the Java Language Specification here is §14.4:
In other words, local variables declarations may only appear as standalone declarations at the level immediately 'below' a block (
{}
). They are not counted asStatements
(§14.5), which are the things that go afterif (....)
.问题是:
...本质上等同于:
您已经定义并初始化了
items
,但是当您退出语句/块时,它会立即超出范围,因此您可以'实际上并没有用它来做任何事情。编译器正在警告您这一点。The problem is that this:
...is essentially equivalent to this:
You've defined and initialized
items
, but when you exit the statement/block, it immediately goes out of scope, so you can't actually use it for anything. The compiler is warning you about that.您在 if 语句中定义变量
items
,因此它无法在该范围之外的任何地方使用。编辑:太慢了...
You're defining the variable
items
in the if statement, so it won't be usable from anywhere outside that scope.EDIT: Too slow...
编译器错误是因为语言的规则没有明确指出“items”变量声明的范围。
例如,如果我有这样的代码块:
很明显 returnValue 是整个方法中的有效变量。
如果我有这样的代码块:
很明显 returnValue 在“if 子句”之外无效。
但是如果我有这样的代码块:
不清楚 returnValue 是否在 if 语句的范围内,或者 returnValue 是否在整个方法的范围内。这是由于Java语言语法的布局细节造成的。基本上,允许在任何块中声明新变量(因为块明确定义了变量的范围),但此 if 语句不包含块。
如果你假设Java默默地为你添加了这个块,那么范围就在“被遗忘的块”之内。如果您假设由于没有显式块来包含范围,则变量的范围与方法的其余部分处于同一级别。关于哪种观点“更”正确的争论比比皆是,因此这种做法的整个尝试都是被禁止的。
如果这对你来说很奇怪,并且你认为只有疯子才会认为变量是在隐含块的范围内定义的,请记住,在 Java 之前的语言中,范围将处于同一级别作为返回语句。是的,按照今天的标准来看,这是疯狂的语言,但它们仍然存在。
The complier error is because the rules of the language doesn't make a clear point on the scope of the variable declaration of "items".
For example, if I have a block of code like this:
it is painfully clear that returnValue is a valid variable across the entire method.
If I have a block of code like this:
it is painfully clear that returnValue is not valid outside of the "if clause".
But if I have a block of code like this:
it is not clear if returnValue is within the scope of the if statement or if returnValue is within the scope of the entire method. This is due to the details of the layout of the Java language grammar. Basically, it's allowed to declare new variables within any block (because a block clearly defines scope of the variable) but this if statement doesn't contain a block.
If you assume that Java adds the block for you silently, then the scope is within the "forgotten block". If you assume that since there's not explicit block to contain the scope, then the scope of the variable is at the same level as the rest of the method. Arguments abound as to which viewpoint is "more" correct, so the entire attempt to do such a thing is forbidden.
If this seems odd to you, and you thing that only a crazy man would not assume that the variable is defined within the scope of an implied block, please remember that there were languages prior to Java where the scope would have been at the same level as the return statement. Yes, crazy languages by today's standards, but they still existed.