Почему инициализация строки в операторе if выглядит иначе, чем в операторе switch?

Я изучаю Java и делаю простые программы, чтобы найти сезон, на котором базируется месяц, основываясь на некоторых книжных примерах. Эти два класса демонстрируют два способа проверки значения: оператор if/else if и оператор switch. То, что меня смущает, это строка, которая используется для проведения сезона. Когда я объявляю это просто String season; это работает с утверждениями if. Но с помощью оператора switch это приводит к ошибке "Возможно, инициализирована локальная переменная сезона".

public class IfElse {
    public static void main(String args[]) {
        int month = 5;
        String season;
            // isn't initialized, works fine

        if(month == 12 || month == 1 || month == 2)
            season = "Winter";
        else if(month == 3 || month == 4 || month == 5)
            season = "Spring";
        else if(month == 6 || month == 7 || month == 8)
            season = "Summer";
        else
            season = "Fall";

        // this is okay
        System.out.println("May is a " + season + " month.");
    }
}

Не инициализация сезона в то же время, когда объявление отлично работает для приведенного выше кода, но переменная сезона в последнем println() для коммутатора выдает ошибку, если она объявлена таким же образом.

Следующий код не работает:

public class Switch {
    public static void main(String args[]) {
        int month = 5;
        String season;
            // HAS to be initialized, currently causes error
        switch(month) {
        case(12):
        case(1):
        case(2): 
            season = "Winter";
            break;
        case(3):
        case(4):
        case(5): 
            season = "Spring";
            break;
        case(6):
        case(7):
        case(8): 
            season = "Summer";
            break;
        case(9):
        case(10):
        case(11): 
            season = "Fall";
            break;

        default:
            System.out.println("Invalid month");
            break;
        }
        System.out.println("May is a " + season + " month");
    }             // produces an error if season isn't initialized to null or ""
}

Что вызывает это? Это фигурные скобки, заключающие оператор switch, или проблема с самим оператором switch? Чем инициализация строки внутри оператора if отличается от инициализации строки внутри оператора switch? Я просто не могу понять это.

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

Ответ 1

Это потому, что вы не указали, какой сезон должен быть в случае по умолчанию. Что происходит, когда месяц не в течение 1-12? season не будет инициализирован.

Если вы ожидаете строго 1-12 в качестве ввода месяца, то вы можете рассмотреть возможность создания Exception по default:

default:
    throw new IllegalArgumentException("Invalid month");

Ответ 2

В вашем первом примере нет пути через код, который не может присвоить значение сезону. Во втором примере регистр по умолчанию не присваивает значение, поэтому последняя печать ("Может быть...") может быть выполнена с неинициализированным значением.

Ответ 3

В вашем коде if/else есть гарантия, что переменная season получит значение. То есть утверждение else.

У вашего кода switch его нет. Посмотрите, что произойдет с переменным season если заданное значение для месяца равно 13 - оно не получит значение и останется не инициализированным.

Ответ 4

Вы должны использовать это

public class Switch {
public static void main(String args[]) {
    int month = 5;
    String season;
        // HAS to be initialized, currently causes error
    switch(month) {
    case 12:
    case 1:
    case 2: 
        season = "Winter";
        break;
    case 3:
    case 4:
    case 5: 
        season = "Spring";
        break;
    case 6 :
    case 7 :
    case 8 : 
        season = "Summer";
        break;
    case 9 :
    case 10 :
    case 11 : 
        season = "Fall";
        break;

    default:
        season = "Invalid";
        break;
    }
    System.out.println("May is a " + season + " month");
}             // produces an error if season isn't initialized to null or ""
}