2014-06-13 43 views
2

我知道关于检查异常的规则,但我无法完全解决这个问题。为什么第二种方法不能编译,但第一种方法呢?最后一个throws语句中的错误是“未处理的异常类型异常”。我可以理解为什么我得到这个错误,但我不明白为什么第一种方法可以,它应该有同样的问题?!Java 7检查异常规则

eclipse和intellij都显示相同的错误。

import java.util.concurrent.Callable; 

public class ThrowableWeirdness { 

    public void doWithMetrics(String name, Runnable runnable) { 

     try { 
      runnable.run(); 
     } catch (Throwable e) { 
      System.out.printf(name + ".failed"); 
      throw e; 
     } 
    } 

    public <RET> RET doWithMetrics(String name, Callable<RET> runnable) { 

     try { 
      return runnable.call(); 
     } catch (Throwable e) { 
      System.out.printf(name + ".failed"); 
      throw e; // Compilation error on this line: unhandled exception 
     } 
    } 
} 

你能解释两种方法的区别吗?

+0

第一种方法在我的Eclipse上都不能编译...你确定你没有忘记在方法签名中抛出一些'Throwable'? – sp00m

+0

是的,同样在这里,两种方法都会给出无用的异常错误。 –

+0

奇怪。我使用Java 7,也许这有所作为。第一种方法定义编译,也运行! –

回答

5
  • 在第一种情况下,runnable.run不抛出任何检查Exception,使您的try/catch和重新抛出不推断扔东西检查,因此它编译
  • 在你的第二个情况下,runnable.call()抛出Exception,是处理,但后来重新出现。

为了修复编译在这种情况下,你必须添加一个throws声明,您的方法声明。

+0

谢谢,这很有道理。只是在java 6中,这两种方法都不能编译,但在java 7中有一个重新抛出异常的修复方法。我想我会转而使用番石榴函数而不是Callable。 –

+0

@DavidRoussel是的,6和7之间的重新抛掷行为是不同的。我不熟悉番石榴,但是我发现它需要使用一个外部框架才能重新抛出行为改变,这有点奇怪... – Mena

+0

实际上最后我为我的目的定义了一个新界面。我想要可调用的东西,但没有检查异常。我不是一个被检查的异常粉丝。 –

2

从Java 7日起,编译器检查try块检查what exception are actually going to be raised

然而,在Java SE 7中,你可以指定异常类型 FirstException和SecondException在在 rethrowException throws子句方法声明。 Java SE 7编译器 可确定语句throw e抛出的异常必须具有来自try块的 ,并且try块 引发的唯一异常可以是FirstException和SecondException。即使catch子句,E的 异常参数的类型是例外, 编译器可以判断它是要么FirstException 或SecondException

如果你设置源代码级别1.6的情况下,他们都不会编译。