2014-01-22 4 views
1

Следующий код не будет компилироваться, потому что компилятор не гарантирует, что поле данных f будет инициализировано. Как вы это исправите?Как инициализировать поле данных внутри цикла?

импорт java.util.Scanner;

public class Foo 
{ 
    private final int f; 
    /*constructor*/ 
    public Foo() 
    { 
     Scanner sc = new Scanner(System.in); 
     for(int i = 0; i < 10; i++) 
       { 
        if(i == 5) 
         f = sc.nextInt();//error: variable f might be assigned in a loop 
       } 
    } 

    public Foo(int i) 
    { 
      j = i;//no problem 
    } 
} 

Не является ли это своего рода глюк в языке, потому что в моем другом конструкторе я могу иметь f набор для final и только потому, что это не сделано в цикле он работает. Я знаю, что компилятор (будучи немым) видит цикл и думает, что f будет переназначен, но логика в программе гарантирует, что это произойдет только один раз. Является ли это примером того, как Java «защищает» программатора?

Для всех интересно, почему f был объявлен окончательным Netbeans, предположил это, предположительно, когда код был сильно иным.

+1

почему й финал? когда вы выполняете итерацию и присваиваете ей значение в другое время? – Hrishikesh

+0

Капля "финала"? – Fildor

+0

Причина в том, что f является окончательным. – Hrishikesh

ответ

2
private final int f; 
     ↑ 

Удалить ключевое слово final. Составители не знают, что if будет выполнен только один раз, и вы получите ошибку о попытке изменить f несколько раз:

Последнее поле F, возможно, уже был назначены

+0

@ user2864740 Спасибо, ты прав, я удалил его. – Maroun

+0

О, мне понравился этот ответ, просто нит-сбор. – user2864740

1

Прежде всего, поле final - это поле, в котором вы не можете изменить значение, которому присвоено значение. В вашем случае в каждом перемещении цикла вы меняете это значение, поэтому его невозможно скомпилировать. Удалите последнее слово перед f.

public class Foo 
{ 
    private int f; 
    /*constructor*/ 
    public Foo() 
    { 
     Scanner sc = new Scanner(System.in); 
     for(int i = 0; i < 10; i++) 
       { 
        if(i == 5) 
         f = sc.nextInt(); 
       } 
    } 
} 
+0

Теперь f не является окончательным: D см. Выше. – RMachnik

+0

Пожалуйста, отметьте этот ответ как принято заранее! – RMachnik

0
private final int f; 

Вы можете использовать окончательный для декларации этого не позволит повторно присвоить другое значение для е

Заключительное переменная может быть инициализирована только раз, либо через инициализаторе или оператор присваивания.

Подробнее о финале here

так просто использовать

private int f; 
0

Когда у объявить любую переменную как окончательное значение этого значения не должно быть changed.By путь есть ли необходимость объявить переменную как final?

1

Вы .. не делаете.

Я знаю, что компилятор (будучи немым) видит цикл и думает, что f будет переназначен, но логика в программе гарантирует, что это произойдет только один раз. Является ли это примером того, как Java «защищает» программиста?

Такое поведение, независимо от того, или нет «защищает» его программисту, является результатом того, как язык Java определяется (в соответствии с JLS) и как компилятор правильно применяет спецификации языка.

4.12.4. final Variables:

Заключительное переменная может быть назначен только один раз .. Это ошибка времени компиляции, если конечная переменная присваивается, если она не является определенно Unassigned (§16) непосредственно перед к заданию.

См Chapter 16. Definite Assignment которая обсуждает правила для этого ограничен статического случая анализа в деталях.

0

Вот улов, вы можете инициализировать любой конечный экземпляр в том же месте или внутри конструктора, но не можете инициализировать внутри метод (МЕТОД).
Итак, вы скажете, что я инициализирую внутри конструктора !! Но дело в том, что вы меняете значение переменной конечного экземпляра в несколько раз внутри цикла, который компилятор идентифицирует и выдает ошибку компилятора.

компилятор встроенный окончательный код, как показано ниже.

private final int f = 10 //even if you initialize it inside the constructor only one time. 

экс

public class Foo { 
     private final int f; // byte code becomes 'private final int f = 10' for each instance 

     Foo() { 
      f = 10; 
     } 
    } 
Смежные вопросы