【问题标题】:Why try/catch around throwable?为什么要尝试/抓住可投掷的东西?
【发布时间】:2011-05-12 22:17:58
【问题描述】:

在尝试重构一些 I 代码时,我尝试像这样在 catch 子句中抛出异常 -

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

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

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

为什么编译器需要这个,它有什么用处?

谢谢

【问题讨论】:

  • 感谢所有答案,代码在线程的 run 方法中,所以我认为我不能抛出异常?
  • Throw error to calling method! 的可能重复项
  • 我不这么认为,但也许我错了,我真正想知道的是为什么我需要用 try catch 包围“抛出异常”。抛出异常时肯定不能抛出异常吗?尝试 { 抛出异常 } 捕捉(异常 e2){ ... }

标签: java checked-exceptions


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 我见过有效的捕捉和重新投掷的案例。那些说......可能正在记录的行。它们可能是异常本身的逻辑等。
  • @Wes - 我说的是代码的“固定”版本。我声称嵌套的try catch 毫无意义。您可以删除 try 块并内联 catch 块,它会以更少的代码行更快地完成同样的事情。
  • 没关系,无论如何我之前都赞成你的答案。我只是对你所说的有点困惑。请注意,这是在我看到您的编辑之前。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    代替

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

    试试

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

    【讨论】:

      【解决方案4】:

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

      以下示例有效

      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-03-13
        • 2011-02-12
        • 1970-01-01
        • 2016-05-11
        • 2011-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多