2012-07-20 167 views
51

我正在调用run()中的一个方法,该类实现了Runnable)旨在引发异常。有没有办法让Runnable的run()抛出异常?

但是Java编译器不会让我这样做,并建议我用try/catch来包围它。

问题是,通过围绕它与一个try/catch我使特别是run()无用。我想抛出异常。

如果我指定throwsrun()本身,编译器会抱怨Exception is not compatible with throws clause in Runnable.run()

通常我完全没有让run()抛出异常。但我有独特的情况,我必须拥有该功能。

如何解决此限制?

+0

除了其他的答案,跟踪任务的进度,可以使用FutureTask类。 – JProgrammer 2012-07-20 17:32:41

+0

非Android的Java的问题:http://stackoverflow.com/questions/1369204/how-to-throw-a-checked-exception-from-a-java-thread?lq=1 – 2015-03-20 14:15:50

回答

15

如果你想通过一个实现Runnable的类到Thread框架中,那么你必须按照该框架的规则进行操作,参见Ernest Friedman-Hill的答案,为什么这么做不是一个好主意。

我有一个预感,但是,你想直接在你的代码中调用run方法,所以你的调用代码可以处理异常。

这个问题的答案很简单。不要使用线程库中的Runnable接口,而是使用修改后的签名创建自己的接口,以允许引发已检查的异常。

public interface MyRunnable 
{ 
    void myRun () throws MyException; 
} 

你甚至可以(通过处理检查除外)适用于线程框架使用创建转换该接口实际Runnable的适配器。

+22

线程如何使用这个接口? – 2013-07-18 12:55:38

+0

这样一个简单的解决方案就是在不考虑“盒子”的情况下达成的。当然,'Runnable'只是一个简单的界面,我们可以自己做。对于线程用例而言,这并不是有用的,但是为了传递不同的“可运行”代码块,这非常完美。 – 2018-03-01 15:46:56

16

如果run()抛出一个检查异常,会发现什么?由于您不写入调用它的代码,因此您无法将该调用附在run()处理程序中。

你可以在run()方法中发现你的检查异常,并且在它的位置抛出一个无例外的异常(即RuntimeException)。这将使用堆栈跟踪来终止线程;也许这就是你所追求的。

相反,如果你希望你的run()方法某处报告错误,那么你可以只提供了run()方法的catch块调用回调方法;该方法可以将异常对象存储在某处,然后您感兴趣的线程可以在该位置找到该对象。

-1

您的要求没有任何意义。如果你想通知被调用的线程有关发生的异常,你可以通过回调机制来完成。这可以通过处理程序或广播或其他任何你能想到的方式。

0

我认为listener pattern可能会帮助你解决这个问题。如果run()方法发生异常,请使用try-catch块并在catch中发送异常事件通知。然后处理你的通知事件。我认为这将是一个更清洁的方法。 This SO link为您提供了一个有用的指向该方向的指针。

59

您可以使用Callable来代替它,将其提交给ExecutorService并等待由ExecutorService.submit()返回的FutureTask.isDone()的结果。

isDone()返回true时,请致电FutureTask.get()。现在,如果您的Callable已抛出Exception,那么FutureTask.get()也会抛出Exception,并且您将可以使用Exception.getCause()访问原始异常。

+5

很想看到一个代码示例 – gromit190 2017-04-06 12:53:30

13

是的,有一种方法可以抛出检查例外的方法,但它非常可怕我不会分享它。

这是你可以做的,而不是;它使用一个运行时异常会行使相同的机制:

@Override 
public void run() { 
    try { 
    /* Do your thing. */ 
    ... 
    } catch (Exception ex) { 
    Thread t = Thread.currentThread(); 
    t.getUncaughtExceptionHandler().uncaughtException(t, ex); 
    } 
} 

正如其他人所指出的,如果你的run()方法确实是一个Thread的目标,有一个在,因为它是不可观测抛出异常,没有点;抛出异常具有与不抛出异常(无)相同的效果。

如果它不是Thread目标,请不要使用Runnable。例如,或许Callable更合适。

+0

但是这会导致进程崩溃时它抛出?? – 2017-09-20 14:09:03

+0

@DineshVG不,只有JVM中的错误才能导致真正的崩溃。默认的异常处理程序只是打印异常。如果您习惯在此之后看到进程退出,那是因为该线程是唯一正在运行的线程,并且它已终止。 – erickson 2017-09-20 14:48:29

+0

我试过(在android instrumentation测试用例中)使用这个用于soap调用,如果我从Soap调用中获得400,我会抛出一个异常。这个soap调用在启动测试用例时从一个线程中调用。这个线程使用这个't.getUncaughtExceptionHandler()。uncaughtException(t,ex);'把它扔到检测测试用例中。添加这一行会导致进程崩溃!不知道为什么。 – 2017-09-20 15:23:44

-1

最简单的方法是定义自己的扩展RuntimeException类而不是Exception类的异常对象。

+0

当您遇到此RuntimeException时,您将如何获得这个RuntimeException?亲爱的先生? – Dormouse 2017-04-07 10:25:27

+0

这并不能回答这个问题。 – 2018-02-02 09:45:16

0

这里是你如何可以换一类具有checked异常,仍然能够覆盖/考全班

public final class Json { 

private Json() { 
} 

public static ObjectMapper standard() { 
    final ObjectMapper objectMapper = new ObjectMapper(); 
    objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 
    objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); 
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 
    objectMapper.setDefaultSetterInfo(JsonSetter.Value.construct(Nulls.AS_EMPTY, Nulls.AS_EMPTY)); 
    objectMapper.findAndRegisterModules(); 
    return objectMapper; 
} 

public static String writeValueAsString(final Object value) { 
    return transformException(() -> standard().writeValueAsString(value)); 
} 

public static String writeValueAsStringPretty(final Object value) { 
    return transformException(() -> standard().writerWithDefaultPrettyPrinter().writeValueAsString(value)); 
} 

static String transformException(final Callable<String> action) { 
    try { 
     return action.call(); 
    } catch (Exception e) { 
     throw new IllegalStateException(e); 
    } 
} 

}

相关问题