为啥在 if 语句中初始化字符串似乎与在 switch 语句中不同? [复制]
Posted
技术标签:
【中文标题】为啥在 if 语句中初始化字符串似乎与在 switch 语句中不同? [复制]【英文标题】:Why does initializing a string in an if statement seem different than in a switch statement? [duplicate]为什么在 if 语句中初始化字符串似乎与在 switch 语句中不同? [复制] 【发布时间】:2019-05-30 15:48:46 【问题描述】:我正在学习 Java,我正在根据一些书籍示例编写简单的程序来查找一个月所在的季节。这两个类演示了两种测试值的方法:if/else if 语句和 switch 语句。我感到困惑的是用于保持季节的字符串。当我将它声明为 String season;
时,它适用于 if 语句。但是使用 switch 语句,这样做会产生“局部变量 season 可能尚未初始化”错误。
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 语句中初始化字符串有何不同?我似乎无法理解这一点。
对不起,如果这是非常明显的问题,或者这似乎是一个愚蠢的问题。
【问题讨论】:
在不起作用的代码中,第13个月是哪个季节? Meta discussion 关于这个问题。 仅供参考,案例值周围不需要括号。case 12:
等很好。
顺便说一句,使用这样的未初始化变量是个好主意,因为它可以清楚地表明您是否考虑了所有路径(但是,如果示例显示您可能没有正确考虑它)。 (反对使用String season = ““;
,这在经验不足的程序员的代码中经常出现)我认为即将推出的案例表达式将使这成为更好的体验。
明确一点(因为没有一个答案是):这与if
vs switch
无关。您的两段代码根本不等效,但您可以编写具有 if
和 switch
的等效代码(表现出任一行为)。
【参考方案1】:
那是因为您没有指定默认情况下必须是什么季节。当月份不在 1-12 之间时会发生什么? season
不会被初始化。
如果您只期望 1-12 作为月份输入,那么您可能需要考虑在 default:
中添加一个 Exception
default:
throw new IllegalArgumentException("Invalid month");
【讨论】:
并指出提问者 if/else 实现中的一个小错误,else 会将任何无效月份设置为Fall
。如果月份设置为 42,它将打印 Fall
。
@DrZoo 你完全正确。我这样做是出于懒惰,因为我知道我永远不会将月份值设置为超出范围,但这也意味着永远不会出现季节未初始化的情况。将 else 更改为 else if 也给了我与 switch 语句中相同的错误。所以我现在意识到我的问题在于何时(或没有)给变量赋值。
@jkofskie 我不想像现在听起来那样刻薄,但问题是你假设这个值永远不会超过 12。当你开始假设事情时,永远不要在编程中假设任何事情(尤其是用户输入)你会遇到问题(在这种情况下,编译器会很好地警告你)。
@KamiKaze 一些假设是有用的。如果您确实知道输入值保证在可接受的范围内,则不需要添加保护子句。防御您知道不会出现的条件可能会导致难以阅读的复杂代码。这里的重点是程序员应该小心地将程序员对程序的了解与编译器知道的或应该知道的分开。【参考方案2】:
在您的第一个示例中,代码中没有路径无法为“season”赋值。在第二个例子中,默认情况下没有赋值,所以最后的打印(“May is...”)可以用一个未初始化的值来执行。
【讨论】:
是的,出于某种原因,我下意识地认为只有当月份的值实际上超出定义的范围时才会出现问题,但我忘记了 Java 不能那样工作。【参考方案3】:在您的if
/else
代码中,可以保证变量season
将获得一个值。即else
语句。
您的switch
代码没有它。如果月份的给定值为13
,看看变量season
会发生什么——它不会得到值,并且将保持未初始化状态。
【讨论】:
【参考方案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 ""
【讨论】:
以上是关于为啥在 if 语句中初始化字符串似乎与在 switch 语句中不同? [复制]的主要内容,如果未能解决你的问题,请参考以下文章