存储Exception实例并重用它是否安全? [英] Is it safe to store an instance of an Exception and reuse it?

查看:110
本文介绍了存储Exception实例并重用它是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否安全:

public class Widget {

    private static final IllegalStateException LE_EXCEPTION
            = new IllegalStateException("le sophisticated way");

    ...

   public void fun() {
      // some logic here, that may throw
      throw LE_EXCEPTION;
   }

   ....
}




  1. 保留异常的实例

  2. 在需要时使用(抛出)

而不是每次都抛出 new 异常?

instead of throwing a new exception each time?

我是否对它感兴趣?安全

我的意思是:没有内存损坏,没有JVM抛出其他异常,缺少类,没有加载坏类(...)。注意:异常将通过网络抛出(远程)。

By safe I mean: no memory corruption, no additional exceptions thrown by JVM, by missing classes, no bad classes loaded (...). Note: the exception will be thrown over network (remoting).

其他问题(可读性,实例维护成本)并不重要。

Other issues (readability, cost of keeping an instance) are not important.

推荐答案

这取决于您对安全的定义。该异常会产生令人误解的堆栈跟踪,我不会将其称为安全。考虑:

It depends on your definition of "safe." The exception will give a misleading stack trace, which I wouldn't call "safe". Consider:

public class ThrowTest {
    private static Exception e = new Exception("t1"); // Line 2

    public static final void main(String[] args) {
        ThrowTest tt;

        tt = new ThrowTest();
        try {
            tt.t1();
        }
        catch (Exception ex) {
            System.out.println("t1:");
            ex.printStackTrace(System.out);
        }
        try {
            tt.t2();                                  // Line 16
        }
        catch (Exception ex) {
            System.out.println("t2:");
            ex.printStackTrace(System.out);
        }
    }

    private void t1() 
    throws Exception {
        throw this.e;
    }

    private void t2() 
    throws Exception {
        throw new Exception("t2");                    // Line 31
    }
}

具有以下输出:

$ java ThrowTest
t1:
java.lang.Exception: t1
    at ThrowTest.<clinit>(ThrowTest.java:2)
t2:
java.lang.Exception: t2
    at ThrowTest.t2(ThrowTest.java:31)
    at ThrowTest.main(ThrowTest.java:16)

请注意 t1 方法是如何从堆栈跟踪中完全丢失的第一个测试用例。根本没有有用的上下文信息。

Note how the t1 method is completely missing from the stack trace in the first test case. There's no useful context information at all.

现在,您可以使用 fillInStackTrace 会在抛出之前填充该信息:

Now, you can use fillInStackTrace to fill in that information just before the throw:

this.e.fillInStackTrace();
throw this.e;

...但这只是为自己工作(您有时忘记)。根本没有任何好处。并非所有的异常都允许您执行此操作(某些异常使堆栈跟踪成为只读)。

...but that's just making work for yourself (work you will forget sometimes). There's simply no benefit to it at all. And not all exceptions allow you to do it (some exceptions make the stack trace read-only).

您已经在评论的其他地方说,这是为了避免代码重复。拥有异常生成器功能可以使您好很多

You've said elsewhere in the comments that this is to avoid "code duplication." You're much better off having an exception builder function:

private IllegalStateException buildISE() {
    return new IllegalStateException("le sophisticated way");
}

(可能是静态最终值如果您愿意。)

(Could be static final if you like.)

然后将其抛出:

throw buildISE();

这样可以避免代码重复而不会误导堆栈跟踪和不必要的Exception实例。

That avoids code duplication without misleading stack traces and unnecessary Exception instances.

以下是应用于上面的内容:

Here's what that looks like applied to the above:

public class ThrowTest {

    public static final void main(String[] args) {
        ThrowTest tt;

        tt = new ThrowTest();
        try {
            tt.t1();                                   // Line 8
        }
        catch (Exception ex) {
            System.out.println("t1:");
            ex.printStackTrace(System.out);
        }
        try {
            tt.t2();                                   // Line 15
        }
        catch (Exception ex) {
            System.out.println("t2:");
            ex.printStackTrace(System.out);
        }
    }

    private static final Exception buildEx() {
        return new Exception("t1");                    // Line 24
    }

    private void t1() 
    throws Exception {
        throw buildEx();                               // Line 29
    }

    private void t2() 
    throws Exception {
        throw new Exception("t2");                     // Line 34
    }
}



$ java ThrowTest
t1:
java.lang.Exception: t1
    at ThrowTest.buildEx(ThrowTest.java:24)
    at ThrowTest.t1(ThrowTest.java:29)
    at ThrowTest.main(ThrowTest.java:8)
t2:
java.lang.Exception: t2
    at ThrowTest.t2(ThrowTest.java:34)
    at ThrowTest.main(ThrowTest.java:15)

这篇关于存储Exception实例并重用它是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆