Java中的对象创建语句不允许使用单行循环.为什么?

Lio*_*ion 19 java

以下程序没有自己的重要性.它只计算使用类计数器内部的静态字段通过使用for循环创建的对象数,如下所示.

package temp;

final class Counter
{
    private static int cnt;

    public Counter()
    {
        cnt++;
    }

    public static int show()
    {
        return(cnt);
    }
}

final public class Main
{
    public static void main(String[] args)
    {
        for (int i=0;i<50;i++)
        {
            Counter counter=new Counter();
        }

        /*for (int i=0;i<50;i++)
            Counter counter=new Counter();*/

        System.out.print("\nNumber of objects constructed:->"+Counter.show()+"\n\n");
    }
}
Run Code Online (Sandbox Code Playgroud)

这里唯一的问题是注释for循环意味着与上面的for循环相同(同样的东西也应用于while循环)根本不起作用导致编译时错误,表明" 不是语句 "意味着在这种特殊情况下,即使for循环只包含一个语句,这对括号也是必需的!为什么?

Jas*_*Cav 27

要理解为什么会发生这种情况,您必须查看语言规范中的Java的Blocks和Statements语法.

ForStatement定义为:

ForStatement:
    for ( ForInitopt ; Expressionopt ; ForUpdateopt )
        Statement
Run Code Online (Sandbox Code Playgroud)

声明定义为:

Statement:
    StatementWithoutTrailingSubstatement
    LabeledStatement
    IfThenStatement
    IfThenElseStatement
    WhileStatement
    ForStatement

StatementWithoutTrailingSubstatement:
    Block
    EmptyStatement
    ExpressionStatement
    SwitchStatement
    DoStatement
    BreakStatement
    ContinueStatement
    ReturnStatement
    SynchronizedStatement
    ThrowStatement
    TryStatement
Run Code Online (Sandbox Code Playgroud)

然后,看看Block:

Block:
    { BlockStatementsopt }

BlockStatements:
    BlockStatement
    BlockStatements BlockStatement

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

您会注意到,在此规范中,LocalVariableDeclarationStatement无效,除非它在块中.但是,因为ForStatement要求它后跟一个语句,所以必须存在括号以使表达式有效.因此,任何局部变量声明在没有括号的循环中都是无效的.

  • JasCav是对的.声明声明与标准命令声明不同,并且不能单独作为循环体(并且可能不是if/else的主体). (2认同)

Jes*_*mos 6

因为您正在创建范围变量.Java告诉你这没有任何作用,因为它所做的就是分配内存,一旦循环再次通过,你就会失去那个并创建一个新内存.从本质上讲,整个循环是一个NOP,这就是为什么它告诉你它减少为无所作为的声明.

循环是NOP我的意思是循环中的声明是NOP.

带有大括号的版本的原因是因为编译器没有检查范围内的用法,因为有大括号.这可能与从一行语句生成的解析树与存在完整循环范围时创建的解析树有关.

  • 是的......我不认为这个答案是对的.编译器没有编译此语句 - 正在抛出错误.如果一个语句没用(一个no-op),它会产生警告(除非你设置你的编译器抛出警告).但是,如果你看看我的答案,你会发现@ Lion的声明对于每个Java语言规范都无效,这就是编译器失败的原因. (3认同)
  • +1为了更清楚,这是因为编译器*知道*你在第二种情况下什么都不做并告诉你.在第一个它没有. (2认同)
  • 这不是真的.构造函数递增一个静态计数器,因此`new Counter()`有副作用,而不是NO-OP (2认同)
  • 有趣的是,这不起作用 - 不是我说它很糟糕,而是编译器会优化掉一些明显有副作用的东西. (2认同)