【问题标题】:Try and Catch loopsTry and Catch 循环
【发布时间】:2018-11-08 02:37:41
【问题描述】:

每当我尝试运行我的代码时,它都会无限打印"Please enter number of hours",直到给出stackoverflow

public static void hoursToDaysAndHours() throws InterruptedException {
    try {
        System.out.println("Please enter number of hours");
        Calc.fNum = Calc.input.nextDouble();
    } 
    catch (Exception e) {   
        hoursToDaysAndHours()
    }
    Calc.sNum = Calc.fNum / 24;
    Calc.awnser = Calc.fNum % 24;
    System.out.print((int) Calc.fNum + " hours = " + (int) Calc.sNum + " days and " + (int) Calc.awnser + " hours");
    Thread.sleep(5000);

    Calc.main(null);
}

Calc 是另一个具有 main 并声明变量的类...这是在 hTDAH 类中...

编辑:正如 cmets 中提到的@Deadpool,main 在部分结束后重复一次......

3
Please enter a Celious Number
f
Please enter a Celious Number
f
Please enter a Celious Number
f
Please enter a Celious Number
fd
Please enter a Celious Number
d
Please enter a Celious Number
f
Please enter a Celious Number
dddddddddd
Please enter a Celious Number
/
Please enter a Celious Number






87654
87654.0Celcius is 157809.2 in Fahrenheit
Please enter a number between 1-4 
1 = AreaOfTriangle 
 ----------------------------------
2 = HoursToDaysAndHours Calculator 
---------------------------------- 
3 = CelciusToFahrenheit Calculator 
----------------------------------
4 = BirthdayGame 
---------------------------------- 

Please enter a number between 1-4 
1 = AreaOfTriangle 
 ----------------------------------
2 = HoursToDaysAndHours Calculator 
---------------------------------- 
3 = CelciusToFahrenheit Calculator 
----------------------------------
4 = BirthdayGame 
---------------------------------- 

【问题讨论】:

  • Calc.input.nextLine() 添加到您的catch 块...给我下一个双倍。没有双倍,所以我会抛出一个异常并保持这个令牌待处理。
  • 使用e.printStackTrace();打印catch-block中的异常,你就知道哪里错了
  • Calc.main(null); 这是递归调用

标签: java function exception try-catch


【解决方案1】:

首先,不要捕获异常。这样做可以捕获几乎所有可能的异常,包括各种你不应该捕获的东西......因为你没有预料到它们,而且你不知道如何从它们中恢复。

其次,如果你发现了一个你没有预料到的异常,你需要弄清楚它是什么,以及是什么导致了它。第一步是打印(或记录)堆栈跟踪。

第三,如果您确实获得了堆栈跟踪,则需要阅读它所说的内容。或者至少,把它展示给能读懂它内容的人。 (例如,我们!)

那么到底发生了什么?

有很多可能的解释,下面是其中的一些:

  1. 如果inputnull 那么

      Calc.input.nextDouble();
    

    将抛出一个NullPointerException。如果您捕获该异常并重试(就像您正在做的那样),那将循环。

  2. 如果扫描器输入流中的下一个标记不是有效的双精度,则nextDouble() 将抛出InputMismatchException 不会超过标记。如果您捕获并重试,您将得到相同的异常......并且您将循环。

  3. 这里可能会出现其他异常并给出相同的结果;例如NoSuchElementExceptionIllegalStateException

  4. 另一种情况是,您可能会因为

    而循环
      Calc.main(null);
    

    在方法结束时调用。这很可能会再次调用您的 Calc 类入口点...导致您循环。

现在堆栈溢出的堆栈跟踪应该允许您区分其中的一些,并且将e.printStacktrace() 添加到处理程序将提供更多。

挑战:尝试这样做/阅读堆栈跟踪,看看您是否可以自己解决


...所以我的理解是我必须将输入转换为双精度

没有。 input 变量可能是 Scanner。您不能将 Scanner 转换为双精度。

根据我上面所说的,我/我们不能(还)告诉你你需要做什么来解决这个问题。但第一步是打印堆栈跟踪并阅读它!


但是Double.parseDouble(Calc.input.next()) 做了哪些Calc.input.nextDouble() 做不到的事情。

它们使用不同的语法规则:

  • Scanner 根据依赖于当前语言环境设置的语法解析数字;见javadoc
  • Double.parseDouble 根据区域设置不敏感的语法解析数字;见javadoc

这可能足以使字符串在一种情况下有效,而在另一种情况下无效。这取决于您尝试解析的字符串...以及您的语言环境。

【讨论】:

  • 使用e.printStacktrace();给我java.util.InputMismatchException at java.base/java.util.Scanner.throwFor(Scanner.java:939) at java.base/java.util.Scanner.next(Scanner.java:1594) at java.base/java.util.Scanner.nextDouble(Scanner.java:2564) at hTDAH.hoursToDaysAndHours(hTDAH.java:8) at Calc.main(Calc.java:21)
  • 这告诉您,您尝试读取的令牌不可解析为 double。
  • @Stephen C 现在可以使用了。但是Double.parseDouble(Calc.input.next()) do that Calc.input.nextDouble; 能做什么。也谢谢大家的支持!!
  • 我不想阻止您学习 Java。但我的建议是,您应该首先使用 Google 来解决诸如 Double.parseDouble(Calc.input.next()) do that Calc.input.nextDouble; 可以做什么等问题。查看来自 DoubleScanner 的每种方法的 Oracle Java 文档类。
【解决方案2】:

一种可能的错误来源: 在Calc.fNum = Calc.input.nextDouble(); 行中,您试图从标准输入流中读取输入并告诉输入应该被解析为双精度。如果输入无法解析为双精度,则会发生异常。

现在查看您的 catch 块,您正在捕获所有异常 (catch(Exception e))。但不是处理异常,而是在 catch 块中对同一函数进行递归调用。

因此,如果您的输入不是可以解析为 double 的内容,则异常会不断发生,并且每次异常被捕获并且函数 hoursToDaysAndHours() 的另一个递归调用发生在 catch 块内。

} catch (Exception e) {
    hoursToDaysAndHours() // Recursive call to the same function.
}

因此,如果您的输入不能被解析为 double,那么您永远不会超出 catch 块。

对函数的每次递归调用都会将当前执行保存到堆栈中。这种情况一直持续到你用完堆栈内存,因此你最终得到一个StackOverflowException

更新:解决问题并完成您正在尝试做的事情的简单方法:

public class HoursToDayConverter {

    public static void hoursToDaysAndHours() throws InterruptedException {
        try {
            System.out.println("Please enter number of hours");
            Calc.fNum = Double.parseDouble(Calc.input.next());
        } catch (NumberFormatException e) {
            System.out.println("Invalid input. Try again.");
            hoursToDaysAndHours();
        }
        Calc.sNum = Calc.fNum / 24;
        Calc.awnser = Calc.fNum % 24;
        System.out.print((int) Calc.fNum + " hours = " + (int) Calc.sNum + " days and " + (int) Calc.awnser + " hours\n");

        Thread.sleep(5000);
        Calc.main(null);
    }
}

【讨论】:

  • 所以我的理解是我必须将input 转换为双精度(对不起,Java 的新手并试图自学)...
  • @stephen-c 在下面的answer 中提出了一些出色的学习点。特别是关于捕捉异常。也就是说,有很多事情可以解决。我建议在codereview.stackexchange.com 上发布您的整个解决方案我已经更新了我的答案以包含一种简单的修复方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-31
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多