Java: 在一个块中使用 Catch 和 throws?

Java: Using Catch and throws in the one block?

catching 和下面的 throwingException 有什么意义?两者都做是不好的做法吗?

  try{

    //something

    } catch (Exception e){

    throw new RuntimeException("reason for exception");
    }

在您的示例中,捕获了 Exception 并抛出了 RuntimeException,这有效地将(可能)已检查的异常替换为不必由调用者,也不由 throws 子句中的 throwing 方法声明。

一些例子:

此代码通过编译:

public void SomeMethod ()
{
    try {

        //something

    } catch (Exception e){
        throw new RuntimeException("reason for exception");
    }
}

此代码未通过编译(假设 "something" 可能会抛出检查异常):

public void SomeMethod ()
{
    //something
}

捕获 Exception 并抛出未经检查的异常(即 RuntimeException)的替代方法是添加 throws 子句:

public void SomeMethod () throws Exception
{
    //something
}

这是捕获一种异常并抛出另一种异常的用例。另一个用例是捕获一种类型的异常并抛出另一种类型的已检查异常(您的方法在其 throws 子句中声明)。有时这样做是为了将一个方法内部可能抛出的多个异常归为一组,只向方法的调用者抛出一种类型的异常(这使得他们更容易编写异常处理代码,并且如果所有这些异常应该以相同的方式处理)。

这称为重新抛出异常,这是一种常见模式。

它允许您更改异常的 class(例如在这种情况下),或者添加更多信息(这里也是这种情况,只要该错误字符串是有意义的)。

附加原始异常通常是个好主意:

throw new RuntimeException("cause of the problem", e);

当您仍然想抛出异常时,有时需要重新抛出一个未经检查的异常(RuntimeException),但您的方法的 API 不允许检查异常。

通常这样的代码用于重新包装异常,也就是转换异常的类型。通常,当您在方法中允许的异常受到限制时,您会这样做,但在内部可能会发生其他类型的异常。例如:

class MyServiceImplementaiton implements MyService {
    void myService() throws MyServiceException { // cannot change the throws clause here
        try {
            .... // Do something
        } catch(IOException e) {
            // re-wrap the received IOException as MyServiceException
            throw new MyServiceException(e); 
        }
    }
}

这个惯用语能够继续向调用者传播异常,同时符合接口中的 throws 子句并隐藏内部细节(IOExceptions 可能发生的事实)。

在实践中,这总是比调用 e.printStackTrace() 更好,后者实际上 "swallow" 错误条件并让程序的其余部分 运行 就好像什么都没发生一样。在这方面,Eclipse 的行为非常糟糕,因为如果开发人员不小心,它往往会自动编写此类不良实践结构。