开发者

Odd compiler error on if-clause without braces

The following Java code is throwing a compiler error:

if ( checkGameTitle(currGame) )
    ArrayList<String> items = parseColumns( tRows.get(rowOffset+1), currGame, time, method );

checkGameTitle is a public static function, returning a boolean. The errors are all of the type "cannot find symbol" with the symbols being variable ArrayList开发者_JS百科, variable String and variable items.

However, if I add {curly braces} then the code compiles with no errors. Why might this be? Is there some ambiguity on the if clause without them?


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


Just because I think it's always helpful in these situations, the relevant part of the Java Language Specification here is §14.4:

Every local variable declaration statement is immediately contained by a block. Local variable declaration statements may be intermixed freely with other kinds of statements in the block.

In other words, local variables declarations may only appear as standalone declarations at the level immediately 'below' a block ({}). They are not counted as Statements (§14.5), which are the things that go after if (....).


The problem is that this:

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

...is essentially equivalent to this:

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

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.


You're defining the variable items in the if statement, so it won't be usable from anywhere outside that scope.

EDIT: Too slow...


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:

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

it is painfully clear that returnValue is a valid variable across the entire method.

If I have a block of code like this:

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

it is painfully clear that returnValue is not valid outside of the "if clause".

But if I have a block of code like this:

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

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜