if语句中的Java变量范围

时间:2014-12-23 16:36:27

标签: java syntax-error

我收到以下代码的编译错误:

if(true)
    int a = 10;
else
    int b = 20;

如果我将其更改为以下代码,则没有编译错误:

if(true) {
    int a = 10;
}
else {
    int b = 20;
}

为什么第一种语法错误,而且语言标准是什么?

5 个答案:

答案 0 :(得分:27)

Java规范说if-then-else语句具有以下形式:

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

StatementStatementNoShortIf可以是各种各样的东西,包括块(用大括号括起来的代码),赋值(已经声明的变量),其他if语句等。

值得注意的是,该列表中缺少声明语句(例如int a;int a = 10;),因此会出现编译错误。

有关完整列表,您可以在此处阅读Java规范: http://docs.oracle.com/javase/specs/

答案 1 :(得分:19)

让我们分析一下您的第一个代码示例对语言设计意味着什么

if(condition)
    int a = 10;
else
    int b = 20;

这意味着我们已根据条件定义了ab。由于我们不知道采用了哪个分支,我们如何在if语句之后使用ab?我们不能(如果可能,那可能会导致奇怪的错误)。

因此,作为语言设计师,我们认为ab在各自的分支之外是不可见的,以避免这些奇怪的错误。但是由于无块分支只能有一个语句,我们已经声明a(或b)只能立即无法访问/不可用,所以这样做是没有意义的。因此,我们决定只允许使用块进行变量声明。一个块可以有多个语句,因此该块中声明的变量可以被其他语句使用。

Java的设计者可能应用了类似的推理,因此他们决定只允许在块中声明。这是通过ifJLS 14.9):

的定义来完成的
IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf

StatementJLS 14.5

Statement:
    StatementWithoutTrailingSubstatement
    ...

StatementNoShortIf:
    StatementWithoutTrailingSubstatement
    ...

StatementWithoutTrailingSubstatement:
    Block
    ...

BlockJLS 14.2):

Block:
    { [BlockStatements] }

BlockStatements:
    BlockStatement {BlockStatement}

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement

LocalVariableDeclarationStatementJLS 14.4),重复它只能在一个直接封闭的区块内发生:

  

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

答案 2 :(得分:13)

JLS-14.4. Local Variable Declaration Statements读取(部分),

  

每个局部变量声明语句都会立即被一个块包含。

JLS-14.9. If Statmenets

  

否则,继续执行,根据结果值进行选择:

     

如果值为true,则执行包含的Statement;当且仅当Statement的执行正常完成时,if-then语句才正常完成。

     

如果值为false,则不执行进一步操作,if-then语句正常完成。

但是,JLS-14.5. Statements不包含变量声明。

在单语句块(仅包含变量定义)的范围内定义两个不同的变量使它们都无法访问。我认为你在三元表达方面有更好的运气

int a = (condition) ? 10 : 20;

int a;
if (condition)
    a = 10;
else
    a = 20;

int a;
if (condition) {
    a = 10;
} else {
    a = 20;
}

请注意,变量a然后被初始化为基于condition的值,并且在该语句之后可以访问。

答案 3 :(得分:6)

  

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

阅读本文 http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.4

答案 4 :(得分:0)

我最好的猜测是你不能有条件地声明变量。

  • 当你没有大括号时,你试图在外部范围内有条件地声明一个变量,这是不允许的。
  • 添加大括号时,您将在该局部范围内创建变量(不允许在这些大括号外使用)