尝试/捕获与抛出exception
这些代码语句是否相同? 他们之间有什么区别?
private void calculateArea() throws Exception { ....do something }
private void calculateArea() { try { ....do something } catch (Exception e) { showException(e); } }
是的,有一个巨大的差异 – 后者会吞噬exception(无可否认),而第一个则会让它传播。 (我假设showException
不会重新抛出它。)
所以,如果你调用第一个方法,“做某事”失败,那么调用者将不得不处理这个exception。 如果你调用第二个方法,并且“做某事”失败,那么调用者将不会看到任何exception…这通常是一件坏事,除非showException
真的处理了exception,修正了错误,肯定calculateArea
已经达到了目的。
你可以告诉这一点,因为你不能自己调用第一个方法, 或者声明你的方法可能抛出Exception
。
是。 声明throws Exception
的版本将需要调用代码来处理exception,而明确处理它的版本则不会。
即简单地说:
performCalculation();
将处理exception的负担转移给主叫方:
try { performCalculation(); catch (Exception e) { // handle exception }
第一个throws Exception
,所以调用者需要处理Exception
。 第二个在内部捕获和处理Exception
,所以调用者不必做任何exception处理。
是的,他们之间有很大的区别。 在第一个代码块中,您将exception传递给调用代码。 在第二个代码块中,你自己处理它。 哪种方法是正确的,完全取决于你在做什么。 在某些情况下,您希望代码处理exception(例如,如果没有find文件并且想要创build该文件),但是在其他情况下,您希望调用代码处理exception(找不到文件他们需要指定一个新的或创build它)。
一般来说,你也不想捕捉一个通用的exception。 相反,您只需要捕获特定的文件,如FileNotFoundException
或IOException
因为它们可能意味着不同的事情。
有一种情况我们不能使用抛出,我们必须使用try-catch。 有一个规则:“重写的方法不能抛出任何额外的exception,而不是其父类抛出”。 如果有任何额外的exception应该使用try-catch来处理。 考虑这个代码片段。 有一个简单的基类
package trycatchvsthrows; public class Base { public void show() { System.out.println("hello from base"); } }
它的派生类:
package trycatchvsthrows; public class Derived extends Base { @Override public void show() { // TODO Auto-generated method stub super.show(); Thread thread= new Thread(); thread.start(); try { thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // thread.sleep(10); // here we can not use public void show() throws InterruptedException // not allowed } }
当我们不得不调用thread.sleep()时,我们不得不使用try-catch,在这里我们不能使用:
public void show() throws InterruptedException
因为重写的方法不能抛出额外的exception。
我认为,“相同”是指行为。
函数的行为可以通过以下方式确定:
1)退货价值
2)抛出exception
3)副作用(即在堆,文件系统等的变化)
在这种情况下,第一个方法传播任何exception,而第二个方法不抛出检查exception,并吞下大部分未经检查的exception,所以行为是不同的。
然而,如果你保证“做某事”从不抛出exception,那么行为将是相同的(尽pipe编译器将要求调用者在第一个版本中处理exception)
– 编辑 –
从APIdevise的angular度来看,这些方法在合同上是完全不同的。 此外,不build议抛出类Exception。 尝试抛出更具体的东西,让调用者更好地处理exception。
如果你抛出一个exception,子方法(覆盖这个)应该处理exception
例:
class A{ public void myMethod() throws Exception{ //do something } } A a=new A(); try{ a.myMethod(); }catch Exception(e){ //handle the exception }
这个方法的调用者将需要捕获这个exception,或者声明它在方法签名中被重新抛出。
private void calculateArea() throws Exception { // Do something }
在下面的try-catch块示例中。 这个方法的调用者不必担心处理exception,因为它已经被处理了。
private void calculateArea() { try { // Do something } catch (Exception e) { showException(e); } }
很多时候你希望调用者处理这个exception。 假设调用者调用另一个调用另一个方法的方法,而不是让每个方法处理这个exception,你可以在调用者处理它。 除非你想在这个方法失败时在其中的一个方法中做某件事。