为什么我无法在 Java 中初始化 switch 内的变量?

问题描述 投票:0回答:7

我只是编程的初学者,所以我找不到解决这个问题的方法。现有的问题似乎要么是其他语言的,要么是我无法理解的。

我正在尝试编写一个小程序,用于返回任何给定日期输入的周特定日期。

import java.util.*;

class bday {
public static void main(String[] args){

    Scanner yearfinder = new Scanner(System.in);
    System.out.println("Please type any year");
    int year = yearfinder.nextInt();

    Scanner monthfinder = new Scanner(System.in);
    System.out.println("Please type any month");
    String textmonth = monthfinder.nextLine();
    int month;

    switch(textmonth) {
        case ("january"):
            month = 1;
            break;
        case ("february"):
            month = 2;
            break;
        case ("march"):
            month = 3;
            break;
        case ("april"):
            month = 4;
            break;
        case ("may"):
            month = 5;
            break;
        case ("june"):
            month = 6;
            break;
        case ("july"):
            month = 7;
            break;
        case ("august"):
            month = 8;
            break;
        case ("september"):
            month = 9;
            break;
        case ("october"):
            month = 10;
            break;
        case ("november"):
            month = 11;
            break;
        case ("december"):
            month = 12;
            break;
        default:
            System.out.println("The month you input was invalid");
        }

    Scanner datefinder = new Scanner(System.in);
    System.out.println("Please type any day");
    int date = datefinder.nextInt();

    System.out.println("The date you gave was " + date + "/" + month + "/" + year);
}
}

    //Jan 1 1900 was a monday.

编译此代码时出现错误,指出“变量月份可能尚未初始化”,同时指向 println 语句中的“月份”。任何情况下的初始化都是无效的还是什么?我在开关外部声明了月份变量...

java initialization switch-statement
7个回答
12
投票

与其他回复相反,您不需要在声明时初始化

month

问题是,如果

textmonth
不是任何文字值,则执行将陷入
default
情况,即月份未初始化。

您可以将其初始化为无效值,例如在

0
情况下为
default
,但也许更好的选择是给出错误消息并中止执行。


6
投票

当你声明

month
时,你应该给它一个默认值(比如 0 或 -1),否则 JVM 无法验证
month
是否会为通向 print 语句的所有程序路径定义。

在这种情况下,如果输入了无效的

month
值,打印语句会输出什么? Java 无法判断。 Java 要么需要为每个变量提供一个默认值,要么需要能够确保每个可能的程序路径都为该变量分配一个值。

因此,您可以将

month
设置为
int month
中的值(默认值),或者使
default
语句中的
switch
情况为其分配一个值(考虑所有程序路径)。这样,无论程序采用什么路径,当您尝试打印它时,
month
都会有一个值。

您可能需要考虑的另一个选项是在给出无效月份时抛出错误并终止程序。由于您没有循环输入,因此单个无效输入也会导致您的输出无效。在这种情况下,最好向用户发出信号,表明他/她的输入是错误的,并强制他们重新开始,而不是让他们的错误传递到输出。


2
投票

问题是 int 是一种基元类型,所有基元类型在运行时都不会给出默认值,因此在尝试修改 int 而不初始化它时会收到此错误,这与引用类型不同,而 Java 为其提供了默认值。

正如您在

default
的情况下看到的,您没有初始化 int 变量
month
因此对于编译器来说,
switch case
可能会转到
default
。如果您在
case switch
之后使用月份变量,则发生这种情况,它没有任何默认值,因此会出现编译器错误。

实际上,如果您 pt

month =0;
或在默认情况下分配任何值,它会编译正常。

您可以阅读更多内容: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html 和: Java:为什么我需要初始化一个原始局部变量?


1
投票

你需要保证在运行时无论

textmont
有哪个值,
month
都会得到一个值,现在,再看看开关..

switch(textmonth) {
        case ("january"):
            month = 1;
            break;
...     

        case ("december"):
            month = 12;
            break;
        default:   //-< HERE is the point....
            System.out.println("The month you input was invalid");
        }

... 并看到

default
情况没有分配给变量
month
..

那么如果发生这种情况,月份将没有初始值...在那里添加正确的赋值,就像其他人之前评论的那样,声明并初始化变量,


0
投票

尝试初始化月份

int month=0;


0
投票

用此更新您的月份声明。

int month = 0;

如果在可能只能有条件执行的语句中完成初始化,则会抛出此错误。 或者,如果您添加一个

default
语句,该语句也将为
month
赋值,它将可以正常编译。


0
投票

Miserable Variable的回答是正确的。另外,现代Java有不同的解决方案。

switch
表情

Java 14 带来了

switch
表达式。开关可以返回一个值。另外,您无需应对失败的烦恼;不需要
break

String textmonth = "march";
int month =
        switch ( textmonth )
        {
            case "january" -> 1;
            case "february" -> 2;
            case "march" -> 3;
            case "april" -> 4;
            case "may" -> 5;
            case "june" -> 6;
            case "july" -> 7;
            case "august" -> 8;
            case "september" -> 9;
            case "october" -> 10;
            case "november" -> 11;
            case "december" -> 12;
            default -> -1;
        };

System.out.println( "month = " + month );

月 = 3

使用对象,而不仅仅是整数

在 Java 8+ 中,我们有现代的 java.time 用于日期时间处理。这些类包括

Month
枚举,一年中每个月(一月至十二月)一个预定义对象。

String textmonth = "march";
Month month =
        switch ( textmonth )
        {
            case "january" -> Month.JANUARY;
            case "february" -> Month.FEBRUARY;
            case "march" -> Month.MARCH;
            case "april" -> Month.AUGUST;
            case "may" -> Month.MAY;
            case "june" -> Month.JUNE;
            case "july" -> Month.JULY;
            case "august" -> Month.AUGUST;
            case "september" -> Month.SEPTEMBER;
            case "october" -> Month.OCTOBER;
            case "november" -> Month.NOVEMBER;
            case "december" -> Month.DECEMBER;
            default -> null;
        };

System.out.println( "month.toString() = " + month );

更好的是,您似乎期待用户用英语输入。

Month
枚举对象以英文命名。因此,将输入转换为全部大写,并按名称请求枚举对象。

String textmonth = "march";
Month month = Month.valueOf( textmonth.toUpperCase( ) );

通过捕获

IllegalArgumentException
来检测错误输入。

String textmonth = "tsunami";
Month month = null;
try
{
    month = Month.valueOf( textmonth.toUpperCase( ) );
} catch ( IllegalArgumentException e )
{
    System.out.println( "Oops, faulty input." );
    throw new RuntimeException( e );
}
© www.soinside.com 2019 - 2024. All rights reserved.