2014-09-03 2 views
3

У меня возникли проблемы с Javac на компиляции этот кусок кода:«переменная может не быть инициализирован», хотя я убедиться, что она

public static int getYear() { 
    Console input = System.console(); 
    Boolean gotYear = false; 
    int year; 

    String userInput = input.readLine(); 

    while (!gotYear) { 
     try { 
      year = Integer.parseInt(userInput); 
      gotYear = true; 
     } catch (Exception e) { 
      System.out.print("Please insert a valid date. "); 
      userInput = input.readLine(); 
     } 
    } 

    return year; 
} 

Javac дает мне ошибку на линии return year;, что «переменная" год ", возможно, не был инициализирован". Но поскольку он находится внутри цикла while, я точно знаю, что он будет инициализирован. Я спросил у T. об этом, и он не смог ответить мне, почему это происходит. Его лучшая догадка заключается в том, что Javac - не очень хороший компилятор для того, чтобы разобраться в этом.

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

+1

только инициализировать год до '-1' – EpicPandaForce

+0

С кодом, который у вас есть, переменная 'year' еще не инициализирована и может не инициализироваться. Что делать, если цикл while не будет выполняться? Просто используйте значение по умолчанию, например -1. – Marko

+0

Не используйте блок catch для потока программы. – Stefan

ответ

6

Ваша переменная года инициализируется в блоке try. Для нас очевидно, что он не выйдет из цикла, пока не будет введено что-то ОК. Но правила компилятора более простые, чем это: поскольку инициализация может быть нарушена за исключением, она считает, что год может быть неинициализирован.

+0

Я бы хотел, чтобы он не выдавал ошибку, хотя .. Если бы это было предупреждение, я бы понял, но ошибка заставляет меня чувствовать себя так плохо о моем коде :( – raphaelgontijolopes

+0

Как @Zhuinden предлагает в комментариях, инициализируйте год по умолчанию значение, когда вы его объявляете, и компилятор больше не будет генерировать ошибку. – Julien

2

Нет. Вы должны инициализировать. Локальные переменные метода метода должны инициализироваться до их использования.

Локальная переменная не получит значения по умолчанию. Вы должны их инициализировать, прежде чем использовать.

0

Необходимо инициализировать локальные переменные. Пройдите This, чтобы понять основы

0

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

1

Представьте себе ситуацию, когда gotYear в

while (!gotYear) 

вычисляет истинной.

В этом случае год не будет инициализирован, так как он находится внутри цикла while.

while (!gotYear) { 
    try { 
     year = Integer.parseInt(userInput); 
     gotYear = true; 
    } catch (Exception e) { 
     System.out.print("Please insert a valid date. "); 
     userInput = input.readLine(); 
    } 
} 

Во время компиляции java-компилятор не вычисляет выражения. Поэтому gotYear может принимать любое из двух значений true или false.

Локальные переменные должны быть инициализированы в той же области, в которой они объявлены. Перед его использованием необходимо выполнить интернализацию.

0

year не присвоено, когда Integer.parseInt(userInput); создает исключение NumberFormatException.

Это gotYear, тогда остается Boolean.FALSE сохранение в цикле, слишком сложное для компилятора. Он думает, что вы каким-то образом выйдете из цикла.

Следующее должно вести себя лучше.

for (;;) { 
    try { 
     year = Integer.parseInt(userInput); 
     break; 
    } catch (Exception e) { 
     System.out.print("Please insert a valid date. "); 
     userInput = input.readLine(); 
    } 
} 

Может компилятор просто может принять:

for (boolean keepAsking = true; keepAsking;) { 
    try { 
     year = Integer.parseInt(userInput); 
     keepAsking = false; 

BTW лучше использовать boolean вместо объекта оболочки класса Boolean.

+0

Знаменитый и настолько уродливый пустой «for (;;)» и «break», который напоминает нам об Basic. – Julien

+0

Могу ли я спросить, почему использование 'boolean 'является предпочтительным (а не' Boolean')? – raphaelgontijolopes

+0

boolean - это примитивный тип (например, int), который содержит true для false. Boolean является дочерним классом Object и содержит логическое значение. Следовательно, он также может быть пустым. –

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