Java 递归导致的无限循环(介绍性)
我试图写一个方法,使人们能够通过扫描器输入整数,而不会因为异常而导致程序崩溃。这是我最初拥有的:(这里,sc是一个Scanner对象) 当我用无效输入测试程序时,启动了一个无限循环,在Eclipse停止之前,多次打印消息和“必须输入一个整数”。 我使用以下代码修复了此问题:Java 递归导致的无限循环(介绍性),java,recursion,infinite-loop,Java,Recursion,Infinite Loop,我试图写一个方法,使人们能够通过扫描器输入整数,而不会因为异常而导致程序崩溃。这是我最初拥有的:(这里,sc是一个Scanner对象) 当我用无效输入测试程序时,启动了一个无限循环,在Eclipse停止之前,多次打印消息和“必须输入一个整数”。 我使用以下代码修复了此问题: public static int inputInt(String message) { int returnval = 0; System.out.println(message); Strin
public static int inputInt(String message) {
int returnval = 0;
System.out.println(message);
String valstring = sc.nextLine();
try {
returnval = Integer.parseInt(valstring);
} catch (Exception ex) {
System.out.println("You must enter an integer.");
inputInt(message);
}
return returnval;
}
为什么第一种方法失败了,而第二种方法没有失败?是否有更干净的方法来实现这一点?是的,有更干净的方法:使用
hasnetint
:
public static int inputInt(String message) {
System.out.println(message);
while (!sc.hasNextInt()) {
sc.nextLine(); // clear the bad input first
System.out.println("You must enter an integer.");
System.out.println(message); // why use recursion? just use a while loop
}
return sc.nextInt();
}
我所做的改变是:
- 使用
,因此不必使用异常hasNextInt
- 添加了
sc.nextLine()代码>(问题的根源)
- 而不是递归,只是做一个while循环(当你可以简单循环时为什么要递归?)
- 消除临时变量
- 使其更具可读性(IMO)
public static int inputInt(String message) {
System.out.println(message);
while (!sc.hasNextInt()) {
sc.nextLine(); // clear the bad input first
System.out.println("You must enter an integer.");
System.out.println(message); // why use recursion? just use a while loop
}
return sc.nextInt();
}
我所做的改变是:
- 使用
,因此不必使用异常hasNextInt
- 添加了
sc.nextLine()代码>(问题的根源)
- 而不是递归,只是做一个while循环(当你可以简单循环时为什么要递归?)
- 消除临时变量
- 使其更具可读性(IMO)
public static int inputInt(String message) {
System.out.println(message);
while (!sc.hasNextInt()) {
sc.nextLine(); // clear the bad input first
System.out.println("You must enter an integer.");
System.out.println(message); // why use recursion? just use a while loop
}
return sc.nextInt();
}
我所做的改变是:
- 使用
,因此不必使用异常hasNextInt
- 添加了
sc.nextLine()代码>(问题的根源)
- 而不是递归,只是做一个while循环(当你可以简单循环时为什么要递归?)
- 消除临时变量
- 使其更具可读性(IMO)
public static int inputInt(String message) {
System.out.println(message);
while (!sc.hasNextInt()) {
sc.nextLine(); // clear the bad input first
System.out.println("You must enter an integer.");
System.out.println(message); // why use recursion? just use a while loop
}
return sc.nextInt();
}
我所做的改变是:
- 使用
,因此不必使用异常hasNextInt
- 添加了
sc.nextLine()代码>(问题的根源)
- 而不是递归,只是做一个while循环(当你可以简单循环时为什么要递归?)
- 消除临时变量
- 使其更具可读性(IMO)
Scanner.nextInt()
具有引发3个异常的能力:
1-inputmaschException
:当下一项不是int
时抛出2-
NoTouchElementException
:当没有下一个事件时3-
非法状态异常
:如果扫描仪
已关闭因此,当您输入非法值(例如“abc”)时,最上面的代码会执行以下操作: 接受“abc”并尝试将其转换为int.(
nextInt()
)。因为“abc”不是一个数字,所以它不能转换,并抛出一个输入不匹配异常
。然而,由于该方法没有成功完成,“abc”被保留为下一个要读取的项目。由于引发了异常,因此catch
块中的代码将运行。它打印出“您必须输入一个整数”,然后再次调用自己,传递自己的消息
。然后它初始化returnval
,并打印出第一次运行时的相同消息
,因为您再次将其传递给自己。然后进入try
块,由于“abc”没有成功读取并留在那里,扫描仪读取“abc”并再次尝试将其转换为int
。当然,这行不通,循环又开始了
解决方案
现在你知道你的问题是什么了,你可以想出一个解决办法。在我看来,最优雅的方法是使用Scanner
方法,hasnetint()
。这将返回一个boolean
,让您知道下一个要读取的项目是否可以转换为int
。例如,如果下一项是“abc”,则该方法将返回false
。对于下一项“1”,该方法将返回true
。因此,如果您这样修改代码,它应该可以工作:
public static int inputInt(String message) {
int returnval = 0;
System.out.println(message);
while(!sc.hasNextInt()) {
sc.nextLine();
System.out.println("You must enter an integer.");
}
returnval = sc.nextInt();
return returnval;
}
此代码的作用是:
1-初始化returnval
并打印消息
2-只要扫描仪没有要读取的
int
,就进入while循环。有效地“等待”下一个int
输入3-一旦有一个
int
要读取,它就会读取int并将值保存在returnval
中4-它向调用者返回
returnval
(慢条斯理赢得了比赛,哈哈。我似乎总是反应迟钝。也许是因为我写了一些小小说作为答案……)问题
Scanner.nextInt()
具有引发3个异常的能力:
1-inputmaschException
:当下一项不是int
时抛出2-
NoTouchElementException
:当没有下一个事件时3-
非法状态异常
:如果扫描仪
已关闭因此,当您输入非法值(例如“abc”)时,最上面的代码会执行以下操作: 接受“abc”并尝试将其转换为int.(
nextInt()
)。因为“abc”不是一个数字,所以它不能转换,并抛出一个输入不匹配异常
。然而,由于该方法没有成功完成,“abc”被保留为下一个要读取的项目。由于引发了异常,因此catch
块中的代码将运行。它打印出“您必须输入一个整数”,然后再次调用自己,传递自己的消息
。然后它初始化returnval
,并打印出第一次运行时的相同消息
,因为您再次将其传递给自己。然后进入try
块,由于“abc”没有成功读取并留在那里,扫描仪读取“abc”并再次尝试将其转换为int
。当然,这行不通,循环又开始了