异常信息为null?

43

我在代码中有一个try-catch语句块,在我的catch块中,我调用e.getMessage()打印异常的详细信息。但是,e.getMessage()总是返回null值。有趣的是,当我调用e.printStackTrace()时,我却没有问题地打印了堆栈跟踪。

以下是我的代码:

try
{
    console = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));
}catch(Exception e)
{
    Log.d("Error", "Error Message: " + e.getMessage()); //e.getMessage is returning a null value
    e.printStackTrace(); //this works. is displaying a SocketTimeOutException
}

我的问题可能是什么原因造成的?我该如何解决?


2
什么是问题?堆栈跟踪和异常消息是两个不同的东西,所以在我看来没有什么需要解决的。 - kostja
1
@kostja:它们不是相关的吗?我认为异常消息是堆栈跟踪的简要描述?因此,如果堆栈跟踪不为空,则异常消息也必须包含一个值? - Arci
1
由于评论区已经太长,我添加了一个答案。 - kostja
5个回答

30

消息和堆栈跟踪是两个不同的信息。虽然堆栈跟踪是必需的,但消息不是。大多数异常都携带有消息,这是最佳实践,但有些异常并没有消息,无法修复。

但您可以为客户提供更便捷的服务,并通过包装无消息的异常或抛出原始异常作为原因的自定义异常来提供消息。下面是一个示例:

throw new  MyRuntimeException("Socket was closed unexpectedly", e);

谢谢您的解释。我本应该更早学会它。 - Arci

13

SocketTimeoutException是一种异常类型。可能只是这个异常(或抛出它的代码)没有提供异常消息,而认为异常类型已经足够明确了。

Log.d("Error", "Error Message: " + e);
或者
Log.d("Error", "Some exception occurred", e);

不要询问消息,而是...


谢谢!但是我如何知道 SocketTimeOutException 是由连接超时还是其他原因引起的? - Arci
1
SocketTimeoutException表示套接字读取或接受超时发生。这就是javadoc所说的。 - JB Nizet
谢谢!那么,只捕获SocketTimeOutException会更好吗?我有点担心,因为就像ConnectException一样,有很多情况可能会触发它。如果我必须向用户显示一个非常具体的错误消息,那么我也必须检查异常的消息。不仅仅是异常的名称。 - Arci
没有太多的情况会出现:"套接字读取或接受超时"。如果你正在进行套接字读取或接受,你应该知道。这样你就可以确切地知道发生了什么以及在哪里。 - JB Nizet

3

e.printStackTrace() 表示实际的堆栈跟踪,几乎总是存在的。然而,消息不一定存在。如果您查看 getMessage() 方法的 Javadoc,您会注意到它可能返回 null。如果您使用带有字符串消息参数的异常构造函数调用,则会有消息 Exception Javadoc


谢谢!所以即使异常是由Java/Android本身抛出的(而不是通过throw new Exception),异常消息仍然可能为空吗?我调用e.getMessage()是因为我想向用户显示错误消息。 - Arci
如果你可以抛出没有消息的异常,那么Android也可以。异常消息是为开发人员而不是用户设计的。Android代码是Java代码。你应该捕获异常,并自己向用户显示适当的错误消息。 - JB Nizet
@JB Nizet:是的。这就是为什么我必须通过异常信息来了解异常的原因。我的计划是这样的:[如果(e.getMessage().contains("连接超时"),则显示“连接超时”]。如果我无法确定异常的主要原因,那么我也无法为用户显示特定的错误消息。 - Arci
异常的类型和抛出位置应足以显示有意义的错误消息。您不应依赖于异常的消息。 - JB Nizet

2

我认为你的代码中抛出的异常没有信息。字符串是null。但当然你可以打印堆栈跟踪。这是两件不同的事情。你将看到堆栈跟踪,但没有消息。


谢谢。我不知道它们是单独的实体。今天刚学到。所以有一些错误 Java 没有提供消息吗? - Arci
1
是的,消息只是可选的。但我认为让消息为空并不是一个很好的软件设计,因为消息可以帮助用户获取有关错误的更详细信息。 - Tobias Breßler

2

尝试将异常本身传递给日志记录器,而不是使用e.getMessage()。 日志记录器通常具有期望Throwable对象的方法,并且日志记录器的默认配置(通常)会打印堆栈跟踪。


@JB Nizet提供了我的建议的例子。 - anilsinaci

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