【问题标题】:Throwing multiple exceptions in Java在 Java 中抛出多个异常
【发布时间】:2010-05-26 11:43:25
【问题描述】:

有没有办法在java中抛出多个异常?

【问题讨论】:

  • 不清楚 OP 是要求“在多个异常中抛出一个”还是“同时抛出多个异常”

标签: java exception


【解决方案1】:

一个方法可以抛出几个异常之一。例如:

 public void dosomething() throws IOException, AWTException {
      // ....
 }

这表明该方法最终可以抛出这两个异常中的一个(以及任何未经检查的异常)。您不能(在 Java 或任何语言 AFAIK 中)同时抛出两个异常,这没有多大意义。

你也可以抛出一个嵌套异常,它包含在另一个异常对象中。但这几乎不能算作“抛出两个异常”,它只是表示由两个异常对象(通常来自不同层)描述的单个异常情况。

【讨论】:

  • 这取决于观点 ;-) 显然没有回答如何抛出多个异常的问题。
【解决方案2】:

你不能抛出两个异常。 IE。你不能这样做:

try {
    throw new IllegalArgumentException(), new NullPointerException();
} catch (IllegalArgumentException iae) {
    // ...
} catch (NullPointerException npe) {
    // ...
}

备选方案 1:异常 A 由异常 B 引起

您可以使用cause-constructor嵌套异常来执行以下操作:

try {
    Exception ex1 = new NullPointerException();

    // Throw an IllegalArgumentException that "wraps" ex1
    throw new IllegalArgumentException(ex1);
} catch (IllegalArgumentException iae) {
    // handle illegal argument...
    throw iae.getCause(); // throws the cause (the NullPointerException)
}

关于链式异常的好文章:Programming.Guide: Chained Exceptions

备选方案2:使用抑制异常

一个异常可以抑制另一个异常。

try {
    Exception ex1 = new NullPointerException();

    // Throw an IllegalArgumentException that "suppresses" ex1
    IllegalArgumentException ex2 = new IllegalArgumentException();
    ex2.addSuppressed(ex1);
    throw ex2;
} catch (IllegalArgumentException iae) {
    // handle illegal argument...
    ... iae.getSuppressed() ... // get hold of the suppressed exceptions
}

关于抑制异常的好文章:Programming.Guide: Suppressed Exceptions

【讨论】:

    【解决方案3】:

    我想您可以创建一个包含捕获的异常列表的异常并抛出该异常,例如:

    class AggregateException extends Exception {
        List<Exception> basket;
    }
    

    【讨论】:

      【解决方案4】:

      抛出多个异常是没有意义的,因为您不能有多个错误(错误可能有多种原因,但任何时候都不能有多个错误)。

      如果需要跟踪原因,可以链式异常:

      } catch (Exception ex) {
          throw new RuntimeException("Exc while trying ...", ex);
      }
      

      这些可以通过getCause()获得。

      【讨论】:

      • 请不要鼓励人们抓基地Exception。此外,为了重新打包异常,我使用了一个项目特定的异常基类。通过这种方式,我可以区分可接受的异常、我已经打包并计划处理的异常以及意外异常。
      • 取决于你所说的错误。在为给定语言开发语义分析器的特定情况下,AST 可能包含多个语义错误,这将有利于“一次”返回给用户,以避免他们必须编译代码才能看到下一个错误一次又一次地弹出。你可以争辩说这种情况不需要异常,一个简单的字符串就足够了。
      • @Novicegrammer:我的设计是有一个包含错误列表的异常,消息是"There were " + errors.size() + " errors:\n" + errors.stream().map(String::valueOf).collect(joining("\n")
      【解决方案5】:

      我见过一种模式,其中自定义异常在内部存储其他异常(不记得,他们为什么这样做),但它是这样的:

      public class ContainerException extends Exception {
      
        private List<Exception> innerExeptions = new Arrayist<Exception>();
      
        // some constructors
      
        public void add(Exception e) {
          innerExceptions.add(e);
        }
      
        public Collection<Exception> getExceptions() {
          return innerExceptions;
        }
      }
      

      它是这样使用的:

      try {
        // something
      } catch (ContainerException ce) {
        ce.add(new RunTimeException("some Message");
        throw ce; // or do something else
      }
      

      稍后在代码中,容器异常被评估并转储到日志文件中。

      【讨论】:

        【解决方案6】:

        要在 Java 中引发多个异常,您首先必须将每个异常抑制为一个自定义异常,然后引发相同的自定义异常。请检查下面的代码 sn-p 以实现相同的效果。

          public class AggregateException extends Exception {
        
        
                public void addException(Exception ex){
        
                addSuppressed(ex);
                exception = true;
            }
        }
        
        
        public class AnyClass{
        
            public AggregateException aggExcep = new AggregateException();
        
            public void whereExceptionOccurs(){
                try{
        
                      //some code
                }catch(Exception e){
        
                      aggExcep.addException(e);
                      //throw aggExcep;
                }  
            }
        }
        

        使用相同的引用 aggExcep 调用方法 addException (显然在 catch 块内)抑制任何异常。 最后,使用 'throw' 关键字显式抛出 aggExcep。

        void addSuppressed(可抛出异常)

        是 Throwable 类的预定义方法,它将指定的异常附加到被抑制的异常以传递此异常。

        【讨论】:

          【解决方案7】:

          您可能会抛出多个不同的异常。例如:

          if (obj == null)
              throw new NullPointerException();
          
          if (some other case)
              throw new IllegalArgumentException();
          
          if (this == this)
              throw new IOException();
          

          此代码可能会引发多个不同的异常,但绝不会同时发生。

          【讨论】:

            【解决方案8】:

            当您处理用户提供的文件的服务器端编译并想要报告错误时,Andreas_D 描述的模式绝对有用。

            例如,如果资源编译失败,您可能会生成 CompilationException。编译可能意味着很多事情。例如,您可以评估最终用户上传的文件中的文本、解析令牌、检查语法错误并确定文件是否有效。最后,这个东西要么是有效的要么是无效的,你想交回一个适当的 CompilationException 来传播回调用堆栈。

            正如 Andreas 所描述的,您可以使用 add() 方法将编译问题添加到您的异常中。这些问题本身不一定是异常,但这取决于您。坚持使用单一异常框架通常会有所帮助,这样您就可以在多个地方使用相同的验证逻辑。

            无论如何,您想要的是通过调用堆栈回退的单个 CompilationException,因为这会告诉框架该事物未编译。如果链条上的任何人想知道原因,那么他们可以通过调用 getCauses() 来解决根本问题。

            从用户界面的角度来看,它也很有用。在通过网络返回之前,可以正确处理保留在异常上的信息,以便您可以向最终用户提供一些关于编译失败原因的信息。

            【讨论】:

              【解决方案9】:

              我不确定您是在询问是否可以一次抛出多个异常,或者我们可以有一个代码来一次处理多个异常。我将尝试回答这两个问题。这是我在 StackOverflow 上的第一个答案,请原谅任何错误。

              1) 如果你想一次抛出多个异常,我认为你不能那样做。考虑一个类似的情况。当您解决数学问题并达到除以 0 的点时,此时只有一个错误,即除以零。所以我想你可以只为给定的语句抛出一个错误。但是,您的 try catch 块中可能存在许多语句,每个语句都可能引发不同的错误。

              2) 如果您想处理/捕获多个错误,有两种方法可以做到。 i) 在 Java 7 之前:

              `try{
                   ...
                   //some method/action that can be a cause of multiple errors,say X and Y
                   ...
               }catch(XException e){
                    //Do something if exception X arises.
               }catch(YException e){
                    //Do something if exception Y arises.
               }
              `
              

              ii) 在 Java 7 之后,您拥有了 multi catch 功能。

              try{
                   ...
                   //some method/action that can be a cause of multiple errors,say X and Y
                   ...
               }catch(XException|YException e){
                 // Take action appropriate to both types of exception.
                ...
               }
              

              我相信这会解决您的疑问。 这是我的第一个答案,欢迎所有建议!

              【讨论】:

                【解决方案10】:

                有一种方法可以抛出多个异常,但不是一次。例如当由于某种原因编译失败时,您的方法只能抛出一个异常。 如果你必须涵盖不同的机会,你可以声明你的方法来抛出所有异常“异常”的父类。 所以,一般来说,如果你声明一个抛出异常的方法,这个方法可以抛出任何类型的异常。

                例如:

                public static void main(String[] args) throws Exception
                {
                  getClipboard();    // throws an UnsupportedFlavorException
                  initIOActivity();  // throw an IOException
                }
                

                我不知道您实际需要知道什么,但也许这会有所帮助。 虽然距离你的帖子已经过去了很多时间^^

                问候

                【讨论】:

                • 如果你想抛出多个这样的异常,你应该真正将你的方法定义为public void method() throws UnsupportedSomethingException, IOException {...}。使用Exception 本身是一种快速的方法,可以让你从正确处理异常中获得大量权力。我只建议在 UI 线程或某个顶层捕获异常,以避免完全崩溃。
                【解决方案11】:

                捎带 aioobe 的回答,我所做的是将每个异常放入一个列表中,然后将它们作为抑制的异常添加到一个新的异常中,然后抛出新的异常:

                例子:

                public JSONObject jsonExceptionExample(int value) throws JSONException {
                    //Create Exception List
                    List<JSONException> jsonExceptions = new ArrayList<>();
                    JSONObject jsonObject = new JSONObject();
                    try {
                
                        //Your code that could throw an Exception
                        jsonObject.put("key", value);
                
                    } catch (JSONException e){
                        //Exception is caught and added to list instead of being thrown
                        jsonExceptions.add(e);
                    }    
                    //Check to see if any Exceptions were caught
                    if (jsonExceptions.size() > 0) {
                        //Create a new Exception to be the 'parent' Exception
                        JSONException jsonException = new JSONException("JSONException(s) thrown");
                        //Iterate through your list of errors
                        for (JSONException e : jsonExceptions) {
                            //Add each one to the parent Exception as 'Suppressed'
                            jsonException.addSuppressed(e);
                        }
                        //Throw your new nested error
                        throw jsonException;
                    }
                    //If no Exceptions were found, resume your code
                    return jsonObject;
                }
                

                如果您在其他地方还没有 List,为了避免导入,您也可以只抛出一个新的异常而不是初始化一个列表,使用 addSuppressed()`` in the catchblock, and later callException.getSuppressed() 将错误添加到它.length > 0``` 来确定是否添加了任何内容,但我只是喜欢该列表的可读性和一般理由,即我不想在没有实际错误的情况下创建异常。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2016-08-10
                  • 2017-08-25
                  • 2015-05-15
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-07-23
                  • 2019-03-04
                  相关资源
                  最近更新 更多