安全吗:

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;
   }

   ....
}
  • 保留异常
  • 的实例
  • 随时使用(抛出)

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

    我是否感兴趣

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

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

    最佳答案

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

    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)
    

    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.

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

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

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

    您已经在注释的其他地方说过,这是为了避免“代码重复”。拥有异常生成器功能可以使更好:
    private IllegalStateException buildISE() {
        return new IllegalStateException("le sophisticated way");
    }
    

    (如果愿意,可以是static final。)

    然后像这样抛出它:
    throw buildISE();
    

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

    这是上面所述的样子:
    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
    1:
    java.lang.Exception:t1
    在ThrowTest.buildEx(ThrowTest.java:24)
    在ThrowTest.t1(ThrowTest.java:29)
    在ThrowTest.main(ThrowTest.java:8)
    2:
    java.lang.Exception:t2
    在ThrowTest.t2(ThrowTest.java:34)
    在ThrowTest.main(ThrowTest.java:15)

    10-08 07:13