1

在尝试重构一些我的代码时,我试图在 catch 子句中抛出异常,如下所示 -

try {
....
}
catch(Exception exception){
.....
throw exception
}

但是,当我尝试在“抛出异常”行上抛出异常时,编译器抱怨我需要在新的 try/catch 中将 throw 子句包围起来,就像这样 -

try
{
  ....
}
catch (Exception exception)
{
  .....
  try
  {
    throw exception
  }
  catch (Exception e2)
  {
     ...
  }
}

为什么编译器需要这个以及它提供什么用途?

谢谢

4

4 回答 4

3

该异常java.lang.Exception是已检查异常。这意味着它必须要么在throws封闭方法的子句中声明,要么在方法体中捕获和处理。

但是,您在“固定”版本中所做的是捕获异常,重新抛出它,然后立即再次捕获它。这没有多大意义。

没有看到真正的代码,不清楚真正的解决方案应该是什么,但我预计问题出在原始try { ... } catch处理程序中:

  • 如果可能,您应该在此时捕获更具体的异常,以便在重新抛出它时,它会被方法的现有throws列表覆盖。

  • 或者,您可以将异常包装在未经检查的异常中并抛出它。

  • 作为最后的手段,您可以更改方法的签名以包含Exception在 throws 列表中。但这是一个非常糟糕的主意,因为它只是将问题推给调用者......并且让开发人员/读者处于不知道会发生什么异常的位置。

于 2011-05-12T22:23:13.023 回答
1

在您的原始代码中,没有任何东西可以捕获抛出的异常。我想你要么必须指定你的函数抛出异常,要么有另一个 try/catch 块,因为编译器建议捕获它。

代替

public void yourFunction(){
  try {
    ....
  }
  catch(Exception exception){
    .....
    throw exception
  }
}

尝试

public void yourFunction() throws Exception{
  try {
    ....
  }
  catch(Exception exception){
    .....
    throw exception
  } 
}
于 2011-05-12T22:23:10.650 回答
1

在 Java 中,已检查异常和未检查异常是有区别的。未经检查的异常基本上可以在代码中的任何地方抛出,如果它没有在某处捕获,它将传播到应用程序的入口点,然后停止进程(通常带有错误消息和堆栈跟踪)。检查异常是不同的:编译器不会让你让它传播,你需要用try-catch块包围任何可能抛出检查异常的代码(如果异常是“抛出异常”是最简单的情况检查异常类的实例),或者您必须标记包含对可能引发检查异常的代码调用的方法,并使用“抛出”声明。如果期望的行为是抛出未经检查的异常,那么你' 需要将异常包装在 RuntimeException 中。如果期望的行为是检查异常,那么您需要在当前方法中添加 throws 声明。

于 2011-05-12T22:26:07.917 回答
0

我的猜测是你试图抛出一个没有被方法声明为它可以抛出的异常类型的异常子类。

以下示例有效

package test.example;

public class ExceptionTest {

    public static void main(String[] args) throws Exception{
        try {
            int value = 1/0;
        } catch (Exception e) {
            System.out.println("woops the world is going to end");
            throw e;
        }

    }

}

但是,此示例将给出错误。

package test.example;

public class ExceptionTest {

    public static void main(String[] args) throws RuntimeException{
        try {
            int value = 1/0;
        } catch (Exception e) {
            System.out.println("woops the world is going to end");
            throw e;
        }

    }

}

请注意,在第二个示例中,我只是捕获了 Exception 而不是 RuntimeException,它不会编译,因为我抛出了未声明的抛出异常,即使我确实声明了 RuntimeException。

是的,异常是 RuntimeException 但编译器不知道。

刚刚想到了第三个工作示例来向您展示。这也有效,因为您抛出的类型与您声明的类型相同。(注意唯一的变化是 catch 块)

package test.example;

public class ExceptionTest {

    public static void main(String[] args) throws RuntimeException{
        try {
            int value = 1/0;
        } catch (RuntimeException e) {
            System.out.println("woops the world is going to end");
            throw e;
        }

    }

}

您需要了解所有这三个答案之间的区别

于 2011-05-12T22:31:23.827 回答