if语句中的Java变量范围[重复]

时间:2021-01-24 22:46:23

This question already has an answer here:

这个问题在这里已有答案:

I received a compilation error for the following code:

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

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

If I change it to the following code, then there is no compilation error:

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

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

Why is the first syntax wrong, and from what language standard?

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

5 个解决方案

#1


27  

The Java specification says that an if-then-else statement is of the following form:

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

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

Where Statement and StatementNoShortIf can be various things including blocks (code surrounded with braces), assignments (to already declared variables), other if statements etc.

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

Of note is that declaration statements (e.g. int a; or int a = 10;) are missing from that list, thus you get a compilation error.

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

For the full list, you can read the Java specification here: http://docs.oracle.com/javase/specs/

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

#2


19  

Lets analyze what your first code example would mean for the language design

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

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

Either it means that depending on the condition we have defined a or b. As we don't know which branch was taken, how do we use either a or b after the if-statement? We can't (and if we could that would probably result in strange bugs).

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

So as language designers we decide that a and b are not visible outside their respective branches to avoid these weird bugs. But as a block-less branch can only have a single statement, we have declared a (or b) only to be immediately unreachable/unusable again, so doing that makes no sense. Therefor we decide that a variable declaration is only allowed with a block. A block can have multiple statements, so variables declared in that block can be used by those other statements.

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

The designers of Java probably applied similar reasoning, so they decided to only allow declaration in a block. This is done through the definition of if (JLS 14.9):

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

IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf

Statement (JLS 14.5)

声明(JLS 14.5)

Statement:
    StatementWithoutTrailingSubstatement
    ...

StatementNoShortIf:
    StatementWithoutTrailingSubstatement
    ...

StatementWithoutTrailingSubstatement:
    Block
    ...

Block (JLS 14.2):

Block(JLS 14.2):

Block:
    { [BlockStatements] }

BlockStatements:
    BlockStatement {BlockStatement}

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement

And LocalVariableDeclarationStatement (JLS 14.4), which repeats that it can only occur within a immediately enclosing block:

和LocalVariableDeclarationStatement(JLS 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.

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

#3


13  

JLS-14.4. Local Variable Declaration Statements reads (in part),

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

Every local variable declaration statement is immediately contained by a block.

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

And

JLS-14.9. If Statmenets

JLS-14.9。如果是Statmenets

Otherwise, execution continues by making a choice based on the resulting value:

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

If the value is true, then the contained Statement is executed; the if-then statement completes normally if and only if execution of the Statement completes normally.

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

If the value is false, no further action is taken and the if-then statement completes normally.

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

However, JLS-14.5. Statements doesn't include variable declaration.

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

Defining two different variables within the scope of a single-statement block (containing just the variable definitions) makes them both unreachable. I think you'd have better luck with a ternary expression

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

int a = (condition) ? 10 : 20;

or

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

or

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

Note that the variable a is then initialized to a value based on the condition and it is reachable after that statement.

请注意,变量a然后根据条件初始化为一个值,并且在该语句之后可以访问。

#4


6  

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.

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

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

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

#5


0  

My best guess is that you cannot declare variables conditionally.

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

  • When you don't have braces, you're trying to declare a variable conditionally in the outer scope, that's not allowed.
  • 当你没有大括号时,你试图在外部范围内有条件地声明一个变量,这是不允许的。

  • When you add the braces, you're creating the variables in that local scope (which are not allowed to be used outside of those braces)
  • 添加大括号时,您将在该局部范围内创建变量(不允许在这些大括号外使用)

#1


27  

The Java specification says that an if-then-else statement is of the following form:

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

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

Where Statement and StatementNoShortIf can be various things including blocks (code surrounded with braces), assignments (to already declared variables), other if statements etc.

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

Of note is that declaration statements (e.g. int a; or int a = 10;) are missing from that list, thus you get a compilation error.

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

For the full list, you can read the Java specification here: http://docs.oracle.com/javase/specs/

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

#2


19  

Lets analyze what your first code example would mean for the language design

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

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

Either it means that depending on the condition we have defined a or b. As we don't know which branch was taken, how do we use either a or b after the if-statement? We can't (and if we could that would probably result in strange bugs).

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

So as language designers we decide that a and b are not visible outside their respective branches to avoid these weird bugs. But as a block-less branch can only have a single statement, we have declared a (or b) only to be immediately unreachable/unusable again, so doing that makes no sense. Therefor we decide that a variable declaration is only allowed with a block. A block can have multiple statements, so variables declared in that block can be used by those other statements.

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

The designers of Java probably applied similar reasoning, so they decided to only allow declaration in a block. This is done through the definition of if (JLS 14.9):

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

IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf

Statement (JLS 14.5)

声明(JLS 14.5)

Statement:
    StatementWithoutTrailingSubstatement
    ...

StatementNoShortIf:
    StatementWithoutTrailingSubstatement
    ...

StatementWithoutTrailingSubstatement:
    Block
    ...

Block (JLS 14.2):

Block(JLS 14.2):

Block:
    { [BlockStatements] }

BlockStatements:
    BlockStatement {BlockStatement}

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement

And LocalVariableDeclarationStatement (JLS 14.4), which repeats that it can only occur within a immediately enclosing block:

和LocalVariableDeclarationStatement(JLS 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.

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

#3


13  

JLS-14.4. Local Variable Declaration Statements reads (in part),

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

Every local variable declaration statement is immediately contained by a block.

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

And

JLS-14.9. If Statmenets

JLS-14.9。如果是Statmenets

Otherwise, execution continues by making a choice based on the resulting value:

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

If the value is true, then the contained Statement is executed; the if-then statement completes normally if and only if execution of the Statement completes normally.

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

If the value is false, no further action is taken and the if-then statement completes normally.

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

However, JLS-14.5. Statements doesn't include variable declaration.

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

Defining two different variables within the scope of a single-statement block (containing just the variable definitions) makes them both unreachable. I think you'd have better luck with a ternary expression

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

int a = (condition) ? 10 : 20;

or

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

or

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

Note that the variable a is then initialized to a value based on the condition and it is reachable after that statement.

请注意,变量a然后根据条件初始化为一个值,并且在该语句之后可以访问。

#4


6  

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.

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

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

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

#5


0  

My best guess is that you cannot declare variables conditionally.

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

  • When you don't have braces, you're trying to declare a variable conditionally in the outer scope, that's not allowed.
  • 当你没有大括号时,你试图在外部范围内有条件地声明一个变量,这是不允许的。

  • When you add the braces, you're creating the variables in that local scope (which are not allowed to be used outside of those braces)
  • 添加大括号时,您将在该局部范围内创建变量(不允许在这些大括号外使用)