Java 为什么没有使用自定义消息重新引发异常的选项?

Java 为什么没有使用自定义消息重新引发异常的选项?,java,exception-handling,Java,Exception Handling,要自定义错误消息,我们需要执行以下操作 抓住例外 将异常包装到另一个异常 重新抛出异常 相反,为什么没有办法更改异常错误消息并重新抛出它 我知道这是一个基本问题,但我很想知道你的意见 例如: try { // Any operation which might throw NumberFormatException. int result = 1 / 0; } catch (NumberFormatException e) {

要自定义错误消息,我们需要执行以下操作

  • 抓住例外
  • 将异常包装到另一个异常
  • 重新抛出异常
相反,为什么没有办法更改异常错误消息并重新抛出它

我知道这是一个基本问题,但我很想知道你的意见

例如:

    try
    {
        // Any operation which might throw NumberFormatException.
        int result = 1 / 0;

    } catch (NumberFormatException e)
    {
        // Observe that if I just throw by 'e' then I will get message as '/ by zero'
        throw e;

        // OR I wrap the exception (optional) and throw new exception with custom message.
        throw new NumberFormatException("<Custom Message> instead of '/ by zero'");

        // Instead, wouldn't it be easy if I could just overwrite the exception message of NumberFormatException?

        // below code isn't valid, but wondering why Java doesn't let me do this?
        e.setMessage("<Custom Message> instead of '/ by zero'");
        throw e;
    }
试试看
{
//任何可能引发NumberFormatException的操作。
int结果=1/0;
}捕获(数字格式)
{
//注意,如果我只是抛出'e',那么我将得到消息'/by zero'
投掷e;
//或者我包装异常(可选)并使用自定义消息抛出新异常。
抛出新的NumberFormatException(“而不是“/by zero”);
//相反,如果我可以覆盖NumberFormatException的异常消息,不是很容易吗?
//下面的代码无效,但想知道为什么Java不让我这么做?
e、 setMessage(“而不是“/按零”);
投掷e;
}

在这种情况下,您可以看到,在添加消息时,原始消息和堆栈跟踪都被保留。

如果您可以更改异常消息,则可以编写一些真正的错误代码。例外情况是方法契约的一部分。它反映了代码深处某个点发生的事情

它是用来交流代码中更深层次的错误。更改此消息与您无关。您可以将消息抛出到其他一些可以处理/理解如何处理此异常的方法,或者捕获异常并抛出自己的异常(如果您愿意)

基本上,该消息是异常的一个固有部分(如果您愿意,它是不可变的)

写这样的东西也不难

catch(Exception e){
    throw new Exception("custom message" ,e);
}
哪一行比以下哪一行短:

catch(Exception e){
    e.setMessage('my custom message');
    throw e;
}

问问你自己,如果你的工作是一个骑马的人,他必须给人a发一封信给人B,你读了信,意识到一些额外的信息需要更新。你会重写这封信并把它放回信封里,还是写一张便条并贴在信封上?

没有
setMessage()
meghod,你可以抛出不同的NFE实例,但原始异常是其原因:

catch (NumberFormatException e) {
    throw new NumberFormatException("<Custom Message> instead of '/ by zero'", e);
}
catch(numberformatexe){
抛出新的NumberFormatException(“而不是“/by zero”,e);
}

保留异常的上下文非常重要,这样stacktrace对调用方尽可能有用。

谢谢。我明白这一点,我只是说明如何定制异常消息。我可能只是记录一个错误并抛出自定义异常来定义我的消息。是的,我总是可以这样做,我只是用NFE来说明它。但是你看,我们正在抛出一个新的例外。。。附加编码对吗?因为类
异常
中没有方法
setMessage
。您可以创建一个扩展NumberFormatException的类,该类使用自定义消息调用超级构造函数并抛出该类的实例,而不是更改消息。是的,我知道没有setMessage方法,所以我提到了“无效代码”,但我只是问为什么不使用公共setMessage方法?它可能会导致不一致的结果。假设应用程序遇到NullPointerException并被抛出,如果我们将消息重置为其他内容,则捕获应用程序可能会发现它不一致。类似于字符串类是final的原因。它是如何导致不一致的?我还是会扔NFE对吧?Ansd调用应用程序检查异常类型,而不是其中的消息(通常)。所有jvm生成的异常都映射到一个特定的消息,该消息在所有应用程序中都是一致的。在一个应用程序中更改消息可能会导致消费应用程序显示已知异常类型的错误消息。这就是为什么只有在构造异常时才能设置消息和实际原因(Throwable)。也许这种推理没有很好的例子,但这是我的想法。谢谢。这是有意义的。难道我不需要为重写(添加)消息而创建额外的对象吗?是的,您创建了另一个对象。但是现在,您所受到的性能影响实际上是不存在的。想象一下,一个内存广泛的应用程序使用有bug的servlet执行此检查,而客户端每秒点击此方法N次?它不会大幅增加GC暂停频率吗?就像现在的JVM一样,我不认为这是个问题。将创建一个链接到旧对象的新对象。对象始终是在代码中创建的。。。99.9%的时间性能瓶颈将出现在代码中的其他地方,而不是创建一些简单对象的代码中。
catch(Exception e){
    e.setMessage('my custom message');
    throw e;
}
catch (NumberFormatException e) {
    throw new NumberFormatException("<Custom Message> instead of '/ by zero'", e);
}