if语句中的Java变量范围

Oru*_*rup 33 java syntax-error

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

if(true)
    int a = 10;
else
    int b = 20;
Run Code Online (Sandbox Code Playgroud)

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

if(true) {
    int a = 10;
}
else {
    int b = 20;
}
Run Code Online (Sandbox Code Playgroud)

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

sun*_*nil 27

Java规范说if-then-else声明的形式如下:

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement
Run Code Online (Sandbox Code Playgroud)

在哪里StatementStatementNoShortIf可各种各样的事情,包括块(代码括号括起来),任务(已声明的变量),其他的if语句等.

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

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

  • @Navin _NoShortIf_用于防止嵌套if语句的情况,其中代码的读者不能轻易地决定(或可能会混淆)else分支属于哪个.这在[Java语言规范的第14.5节](http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.5)中进行了解释. (3认同)
  • 这应该足以回答这个问题,对于有这种错误的c ++程序员来说只是有点意外. (2认同)

Mar*_*eel 19

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

if(condition)
    int a = 10;
else
    int b = 20;
Run Code Online (Sandbox Code Playgroud)

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

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

Java的设计者可能应用了类似的推理,因此他们决定只允许在一个块中进行声明.这是通过if(JLS 14.9)的定义完成的:

IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf
Run Code Online (Sandbox Code Playgroud)

Statement(JLS 14.5)

Statement:
    StatementWithoutTrailingSubstatement
    ...

StatementNoShortIf:
    StatementWithoutTrailingSubstatement
    ...

StatementWithoutTrailingSubstatement:
    Block
    ...
Run Code Online (Sandbox Code Playgroud)

Block(JLS 14.2):

Block:
    { [BlockStatements] }

BlockStatements:
    BlockStatement {BlockStatement}

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement
Run Code Online (Sandbox Code Playgroud)

并且LocalVariableDeclarationStatement(JLS 14.4)重复说它只能在一个直接封闭的块内发生:

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


Ell*_*sch 13

JLS-14.4.地方变量声明声明(部分),

每个局部变量声明语句都立即由一个块包含.

JLS-14.9.如果是Statmenets

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

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

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

但是,JLS-14.5.声明不包括变量声明.

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

int a = (condition) ? 10 : 20;
Run Code Online (Sandbox Code Playgroud)

要么

int a;
if (condition)
    a = 10;
else
    a = 20;
Run Code Online (Sandbox Code Playgroud)

要么

int a;
if (condition) {
    a = 10;
} else {
    a = 20;
}
Run Code Online (Sandbox Code Playgroud)

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


Lal*_* J. 6

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

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

  • @JuanMendes第二个版本立即包含在一个块中. (3认同)