调用'System.out.println()'时传入的'Throwable'类型参数'ex'

7

我目前正在开发一个库存管理系统。在系统中,有以下注册选项:

注册页面

以下代码显示了注册按钮的方法:

        btnRegister.setOnAction(e ->{// register button method
            try {
            Stage stage = new Stage();
            FXMLLoader loader = new FXMLLoader();
            Pane root =         loader.load(getClass().getResource("Register.fxml").openStream());
            RegisterController Msg = loader.getController();
            Scene scene = new Scene(root);
            scene.getStylesheets().setAll(
                getClass().getResource("style.css").toExternalForm()
            );
            stage.setScene(scene);
            stage.show();
            ((Node) e.getSource()).getScene().getWindow().hide();

            } catch (Exception ex) {
                System.out.println(ex);
            }
        });

我遇到了以下警告:

Warning:(64, 36) Throwable argument 'ex' to 'System.out.println()' call

请问有人能解释一下这个警告并且提供可能的解决方法吗?

如果忽略这个警告,后续的新更改是否会受到影响?

它在 register 方法中检测到代码的以下行,特别是异常所在的位置:

} catch (Exception ex) {
     System.out.println(ex);
}

3
使用System.out.println(ex);打印会输出ex.toString(),这可能不是很有用。要打印出错误信息,请使用ex.printStackTrace(); - c0der
2
没有堆栈跟踪,很难确定问题发生的位置。如果有嵌套异常,你可能会隐藏实际问题是什么。请参阅什么是堆栈跟踪,如何使用它来调试应用程序错误? 了解为什么堆栈跟踪是有帮助的。 - Slaw
2个回答

11

你应该调用ex.printStackTrace()

使用System.out.println(ex)会隐藏很多有用的信息,甚至可能是至关重要的信息。例如,如果你运行以下代码:

package com.example;

public class Main {

  public static void main(String[] args) {
    try {
      throwException();
    } catch (Exception ex) {
      System.out.println(ex);
    }
  }

  public static void throwException() throws Exception {
    throw new Exception("something went wrong");
  }
}
您将获得以下输出:
java.lang.Exception: something went wrong

那只告诉你异常的类型和错误信息。对于简单的应用程序,这可能足够知道问题是什么以及在哪里。但考虑一个有数千行代码的复杂应用程序;这种异常报告不会告诉您问题发生的位置。

现在将 System.out.println(ex) 替换为 ex.printStackTrace(),然后您将看到新的输出:

java.lang.Exception: something went wrong
    at com.example.Main.throwException(Main.java:14)
    at com.example.Main.main(Main.java:7)

这是堆栈跟踪。从堆栈跟踪中,您可以看到执行流程,还可以查看哪些特定代码行抛出了异常。请注意,您可以配置编译以丢弃调试信息,这意味着您将停止获得源文件名称和行号,但仍将提供类和方法名称(总比没有好)。

Java中的异常不仅如此。异常还可以具有原因以及多个压制异常。 这在Throwable文档中有更详细的描述。这里是一个(人为制造的)例子:

package com.example;

import java.io.IOException;

public class Main {

  public static void main(String[] args) {
    try {
      throwException();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  public static void throwException() throws Exception {
    IOException ioe = new IOException("could not write to stream");
    // typically suppressed exceptions come from a try-with-resources statement
    ioe.addSuppressed(new IOException("unable to close stream"));

    throw new Exception("something went wrong", ioe);
  }
}

这将产生以下输出:

java.lang.Exception: something went wrong
    at com.example.Main.throwException(Main.java:19)
    at com.example.Main.main(Main.java:9)
Caused by: java.io.IOException: could not write to stream
    at com.example.Main.throwException(Main.java:16)
    ... 1 more
    Suppressed: java.io.IOException: unable to close stream
        at com.example.Main.throwException(Main.java:17)
        ... 1 more
如果使用System.out.println(ex),则无法获取任何Caused by:Suppressed:部分。这意味着您不知道实际问题是什么,也不知道是否存在隐藏的问题,这很可能会使修复问题变得更加困难。另外,System.out.println(ex)ex.printStackTrace()之间还有另一个区别。前者将打印到标准输出流(即System.out),而后者将打印到标准错误流(即System.err)。由于异常属于错误,因此将其打印到错误流是有意义的,但是您可以通过Throwable#printStackTrace(PrintStream)Throwable#printStackTrace(PrintWriter)更改目标。例如,ex.printStackTrace(System.out)将在标准输出中打印堆栈跟踪。最后,对于“真正”的应用程序,您可能希望使用日志记录框架。这些框架可以输出更多信息,例如报告异常的线程以及异常发生的时间戳。请查看What is a stack trace, and how can I use it to debug my application errors?问答,以更好地了解堆栈跟踪及其有用性。

6

为了打印异常详细信息,异常类已经具有名为"printStackTrace()"的方法。

 System.out.println(ex); //not recommended 

使用这个

ex.printStackTrace();

3
建议添加解释为什么不建议使用 System.out.println(ex); - c0der
1
这会将堆栈跟踪打印到 System.err 而不是 System.out。由于原始代码正在将输出写入 System.out,因此 ex.printStackTrace(System.out) 更接近原始代码。(但从逻辑上讲,输出确实属于错误流。) - fabian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接