【问题标题】:How to re-throw an exception如何重新抛出异常
【发布时间】:2012-06-29 10:25:24
【问题描述】:

在我的 onCreate() 中,我设置了一个 UncaughtException 处理程序,如下所示:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
       Log.e(getMethodName(2), "uncaughtException", throwable);
       android.os.Process.killProcess(android.os.Process.myPid());
    }
});

它工作正常,但我想恢复系统向用户显示强制关闭对话框的默认行为。

如果我尝试用 throw throwable 替换 KillProcess() 调用,编译器会抱怨我需要用 try/catch 包围它。

如果我用 try/catch 包围它:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        try {
            Log.e(getMethodName(2), "uncaughtException", throwable);
            throw throwable;
        }
        catch (Exception e) {           
        }
        finally {               
        }
    }
});

编译器仍然抱怨 throw throwable 需要用 try/catch 包围。

如何重新投掷该可投掷物?这样,除了信息丰富的Log.e() 之外,系统的行为与以前完全相同:因为我从未设置默认的 UncaughtException 处理程序。

【问题讨论】:

    标签: java android rethrow uncaughtexceptionhandler


    【解决方案1】:

    试试:

    public class CustomExceptionHandler implements UncaughtExceptionHandler {
    
        private UncaughtExceptionHandler defaultUEH;
    
        public CustomExceptionHandler() {
            this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
        }
    
        public void uncaughtException(Thread t, Throwable e) {
            Log.e("Tag", "uncaughtException", throwable);
            defaultUEH.uncaughtException(t, e);
        }
    }
    

    然后 Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());

    改编自this答案。

    【讨论】:

    • 对不起,但这会导致无穷无尽的未捕获异常,并且根本没有强制关闭对话框。不是我要找的。​​span>
    【解决方案2】:

    如果您设置默认的未捕获异常处理程序,您应该在其中消费异常。这反映在uncaughtException 没有声明任何异常这一事实上。

    应该没有明显的理由重新抛出它。它只会在日志中第二次打印出来,无论如何线程都会死掉。如果你真的想要,那么只需将 throwable 包裹在 RuntimeException 中并重新抛出即可。

    【讨论】:

    • 我理解并同意应该没有明显的理由重新抛出它。我定义默认 UncaughtException 处理程序的唯一原因是因为 第一次没有日志!。所以如果系统不打印堆栈跟踪,想打印它。因此处理程序。我对系统的默认行为非常满意,除了它无法解释无法打印来自android.net.http.HttpsConnection.openConnection() 的未捕获异常的堆栈跟踪。 +1。
    【解决方案3】:

    没有理由重新抛出 Throwable,根据 javadoc, it is simply ignored. 线程在此时终止,您只是设置退出前要尝试的任何最后操作。

    为了争论,如果你确实想重新抛出一个 throwable,你会做这样的事情:

    public void reThrow(Throwable t) {
        if (RuntimeException.class.isAssignableFrom(t.getClass())) {
            throw (RuntimeException)t;
        } else if (Error.class.isAssignableFrom(t.getClass())) {
            throw (Error) t;
        } else {
            throw new UndeclaredThrowableException(t);
        }
    }
    

    【讨论】:

    • +1。我什至不会尝试重新投掷,因为我同意你的说法(见 my comment 至 @AlexGitelman)。不过,向用户显示熟悉的强制关闭对话框会很好。知道该怎么做吗?
    【解决方案4】:

    首先,您不需要重新抛出异常。 uncaughtException() 不消耗异常。但是,您必须调用默认的未捕获异常处理程序的方法。比如,

    class MyUEH implements UncaughtExceptionHandler {
      private static final UncaughtExceptionHandler default = Thread.getDefaultUncaughtExceptionHandler();
    
        public void uncaughtException(Thread t, Throwable e) {
            Log.e("Tag", "uncaughtException", throwable);
            default.uncaughtException(t, e);
        }
    }
    

    其次,您不需要自己杀死进程。当你调用它时,默认的 UEH 会处理它。

    第三,默认 UEH 将向用户显示(或导致显示)标准崩溃(强制关闭)对话框。请记住,如果您的方法挂起(例如因为您正在执行 IO),那么在您的方法退出之前,用户将不会看到崩溃对话框。

    【讨论】:

    • 我喜欢你的回答,但事实是,如果我在处理程序的第一个版本中注释掉 killProcess() 语句(只留下 Log.e() 语句,则不会显示强制关闭对话框并且应用程序的视图只是冻结,直到我手动强制关闭应用程序。
    • 是的,你是对的。我忘记了调用默认 UEH 的花絮。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 2021-10-05
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多