【问题标题】:Custom Exception Try Throw Catch in Java自定义异常尝试在 Java 中抛出 Catch
【发布时间】:2020-01-10 03:15:36
【问题描述】:

当变量 d1 和 d2 的数据类型不正确时,我总是收到默认的 NumberFormatException 消息。

我想在使用 throw 语句条件捕获这些异常时打印我的自定义异常消息。

public static void main(String[] args) {

    Scanner sc = new Scanner(System.in);

    System.out.print("Enter a numeric value: ");
    String input1 = sc.nextLine();
    Double d1 = Double.parseDouble(input1);
    System.out.print("Enter a numeric value: ");
    String input2 = sc.nextLine();
    Double d2 = Double.parseDouble(input2);
    System.out.print("Choose an operation (+ - * /): ");
    String input3 = sc.nextLine();
    try {
        if (!(d1 instanceof Double)) {
            throw (new Exception("Number formatting exception caused by: "+d1));
        }
        if (!(d2 instanceof Double)) {
            throw (new NumberFormatException("Number formatting exception caused by: "+d2));
        }
        switch (input3) {
            case "+":
                Double result = d1 + d2;
                System.out.println("The answer is " + result);
                break;
            case "-":
                Double result1 = d1 - d2;
                System.out.println("The answer is " + result1);
                break;
            case "*":
                Double result2 = d1 * d2;
                System.out.println("The answer is " + result2);
                break; 
            case "/":
                Double result3 = d1 / d2;
                System.out.println("The answer is " + result3);
                break;
            default:
                System.out.println("Unrecognized Operation!");
                break;
        }
    }
    catch (Exception e){ 
        System.out.println(e.getMessage());
    }

}

}

这是输入值格式不正确时打印的消息示例。

输入一个数值:$ 线程“main”java.lang.NumberFormatException 中的异常:对于输入字符串:“$” 在 java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054) 在 java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) 在 java.base/java.lang.Double.parseDouble(Double.java:543) 在 com.example.java.Main.main(Main.java:13)

【问题讨论】:

  • 这是因为,正如堆栈跟踪所指出的,错误发生在 parseDouble 中,在您输入不是数字的内容后立即发生。执行甚至都不会“将东西放入d1”,代码抛出,因此在分配发生之前退出main()
  • 如果String 参数无法解析为Double,则对Double#parseDouble(String) 的调用将抛出NumberFormatException。这些调用发生在您尝试抛出自己的异常之前。此外,d1d2 将始终是 Double 的实例,因为它们声明的类型是 Double 并且它们不能是 null——你永远不会将它们设置为 nullparseDouble 永远不会返回 @987654337 @(该方法实际上返回原始类型double)。

标签: java exception


【解决方案1】:

您的代码的问题是您在尝试解析它之后进行了很好的检查。

你的主要线索是你得到的堆栈跟踪。它清楚地表明在第 13 行的parseDouble 处引发了异常。这是在您自己检查之前,程序永远不会到达它。

您的下一步应该是检查Double.parseDouble 的Javadoc,以查看它返回的内容和抛出的时间。

阅读的文档(我遗漏了一些与问题无关的内容):

Returns a new double initialized to the value represented by the specified String

Throws:
    NullPointerException - if the string is null
    NumberFormatException - if the string does not contain a parsable double.

这意味着,如果你使用这个方法来解析你的双打,那么它抛出无效输入。

下一步做什么取决于你的目标是什么。抛出异常的两个主要问题是:
- 你想要你的自定义异常,而不是默认的
- 你想避免额外的异常(以免产生堆栈跟踪等)

如果您属于第一类,那么解决方案很简单 - 将 parseDouble 放入 try 块中,如果失败则重新抛出自定义异常,如下所示:

double d1;
try {
    d1 = Double.parseDouble(input1);
catch (NumberFormatException | NullPointerException e) {
    throw new MyCustomException("Please enter a valid double!", e);
}

如果你这样做了,那么你不需要再次检查你的 try/switch 块(你已经保证输入是一个有效的类型!)

如果您想完全避免使用NumberFormatException,那么最好的办法是遵循Javadoc 上的建议,并在尝试解析之前使用正则表达式对字符串进行预检查。

【讨论】:

  • 变量必须在 try 块之外初始化,否则它们不能在程序的后续范围内调用。这就是为什么我在最初发布的代码中的 try 块之前有 parseDouble 语句。
  • @DarnocEloc 这是不正确的。它们只需要在使用该变量的每个有效路径上进行初始化。如果你在你的 catch 块中重新抛出,那么你以后可以毫无问题地使用它们。
  • 你能提供一个这个概念的实现例子吗?我将 try catch 块包含在更大的外部范围内,这允许我在 switch 语句中调用变量,但不能在 catch 块中调用。
  • @DarnocEloc 我的答案中的那个工作正常。您只需要在try 块外声明,在tryinitializeabort(通过throw 或return@987654332 @catch`。之后就可以无限制地使用变量了。
  • 当我试图在 catch 块中抛出一个新异常时,我得到一个“CustomException”无法解析为类型错误或一个未处理的异常类型“Exception”错误。
猜你喜欢
  • 1970-01-01
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-05
  • 2011-10-06
相关资源
最近更新 更多