2013-10-09 2 views
5
public class Test{ 
    public void newMethod(){ 

     if(true)int i=0; 

    } 
} 

Приведенный выше код дает мне следующую ошибкуЗачем нужны скобки здесь? Java: "if (true) int i = 0;"

Test.java:4: error: '.class' expected 
     if(true)int i=0; 
       ^

Но если я это пишу, как этот

public class Test{ 
    public void newMethod(){ 

     if(true){ 
     int i=0; 
     } 

    } 
} 

тогда нет никакой ошибки!

Я знаю, что этот вопрос не помогает сообществу, но мне действительно интересно, почему мне нужно иметь скобки в этом утверждении. Я программировал в java в течение нескольких лет, и только сейчас я столкнулся с этой ошибкой.

Я использую JGrasp, кстати.

+2

всегда использовать скобки ... – aldanux

+8

Я не Java программист, но я полагаю, потому что однозадачная версия 'if' не разрешает объявления переменных. И почему это нужно, поскольку ничто никогда не сможет использовать эту переменную? –

+0

Это на самом деле имеет большой смысл! Я не знаю, как я это забыл. – TonyTerminator

ответ

7

Вот мое понимание. Цитата из Chapter 14 of JAVA SE 7 specification:

14.2. Блоки

Блок представляет собой последовательность операторов, локальных деклараций классов и операторов локальных переменных в фигурных скобках.

Block: 
    { BlockStatementsopt } 

........  

BlockStatement: 
    LocalVariableDeclarationStatement 
    ClassDeclaration 
    Statement 

Так блок всегда в фигурных скобках { ... }.

14.4. Локальные заявления о декларации переменных

Локальный оператор объявления переменных объявляет одно или несколько локальных имен переменных .

LocalVariableDeclarationStatement: 
    LocalVariableDeclaration ; 

LocalVariableDeclaration: 
    VariableModifiersopt Type VariableDeclarators 

....... 

VariableDeclarator: 
    VariableDeclaratorId 
    VariableDeclaratorId = VariableInitializer 

.......

Каждый местный оператор объявления переменных немедленно содержащихся в блоке. Локальные инструкции описания переменных могут быть смешаны с свободно с другими видами операторов в блоке.

Теперь, что это значит, «немедленно содержится»?

Некоторые утверждения содержат другие утверждения как часть их структуры; такие другие утверждения являются подстановками инструкции. Мы говорим, что оператор S сразу содержит оператор U, если нет оператора T, отличного от S и U, такого, что S содержит T и T содержит U. В таким же образом некоторые утверждения содержат выражения (§15) как часть их структуры.

Давайте посмотрим на ваш пример:

public class Test{ 
    public void newMethod(){ 

     if(true)int i=0; 

    } 
} 

В этом случае мы имеем следующий блок:

{ 

      if(true)int i=0; 

} 

Внутри этого блока мы имеем If Statement:

if(true)int i=0; 

Этот оператор, в свою очередь, содержит локальный var iable declare:

int i=0; 

Таким образом, состояние нарушено. Напомним: Каждый локальный оператор объявления переменной немедленно содержится в блоке. Однако в этом случае объявление локальной переменной содержится в инструкции If, которая не является самим блоком, а содержит другой блок. Следовательно, этот код не будет компилироваться.

Единственное исключение для for цикла:

A local variable declaration can also appear in the header of a for statement (§14.14). In this case it is executed in the same manner as if it were part of a local variable declaration statement. 

(Вам может понадобиться перечитать его несколько раз, чтобы понять.)

+0

Думаю, вы должны начать с [14.9: оператор if] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-14 .html # jls-14.9) и посмотрите, что разрешенная вещь, которая следует за if, является 'Statement'. Выражения определены в [14.5] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.5) и явно не содержат объявления переменных. Единственный содержит только отдельные конкретные утверждения (вещи, которые вы ожидаете здесь) и «Блок», которые будут определены, как вы объясняли ранее, и это единственное место, где могут быть размещены объявления переменных. – poke

+0

@poke: да, но 14.4 называется «Локальные заявления о декларации переменных», что несколько сбивает с толку, хотя 14.5 не перечисляет объявления локальных переменных среди операторов. – osa

1

Dark Falcon прав, если один оператор, следующий за тегом if, является объявлением переменной, тогда ничто не может использовать эту переменную, объявление будет ограничено по объему телу if, что было бы бесполезно, потому что что-либо после этого не было бы i в сфере охвата.

Если if (true)int i = 0; действительно работал (это означает, что объявление было видимым для последующих строк), это означало бы, что если бы была объявлена ​​переменная, это зависело бы от результата теста if, что было бы нехорошо.

КСТАТИ if (true) int i = 0; причины такой синтаксис ошибки в Eclipse:

Multiple markers at this line 
    - i cannot be resolved to a variable 
    - Syntax error on token "int", delete 

, помещая скобки вокруг компилирует, хотя она генерирует предупреждение:

the value of the local variable i is not used 
+0

Интересно, почему разработчики думали включить это как ошибку. – TonyTerminator

+0

@TonyTerminator: они были очень тщательными. Возможно, они написали генераторы кода, которые создали бессмысленный код и хотели захватить как можно больше ошибок. –

+1

@TonyTerminator: таким образом им приходилось делать меньше работы.Каждый раз, когда вы объявляете переменную, она включает в себя распределение памяти, изменение области видимости и т. Д. Они приняли решение разрешать объявления переменных непосредственно внутри блоков '{}'. В конце концов, разрешить его в других местах не так полезно, как уже отмечали другие люди, а более строгая и более кратка - это грамматика, тем легче учиться и чем меньше ошибок вы будете делать. Они пытались улучшить C++ с его безграничными возможностями, сделав Java более надежным и более предсказуемым. Да, они в конечном итоге меняют некоторые семантики ... – osa

Смежные вопросы