简体   繁体   English

在 Java 中抛出多个异常

[英]Throwing multiple exceptions in Java

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

A method can throw one of several exceptions .一个方法可以抛出几个异常之一 Eg:例如:

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

This signals that the method can eventually throw one of those two exceptions (and also any of the unchecked exceptions).这个信号,该方法可以最终抛出这两个例外之一(还有任何unchecked异常)。 You cannnot (in Java or in any language AFAIK) throw simultaneously two exceptions, that would not make much sense.您不能(在 Java 或任何语言 AFAIK 中)同时抛出两个异常,这没有多大意义。

You can also throw a nested Exception, which contains inside another one exception object.您还可以抛出一个嵌套的Exception,其中包含另一个异常对象。 But that would hardly count that as "throwing two exceptions", it just represents a single exception case described by two exceptions objects (frequently from different layers).但这几乎不能算作“抛出两个异常”,它只是表示由两个异常对象(通常来自不同层)描述的单个异常情况。

I suppose you could create an exception containing a list of caught exceptions and throw that exception, eg:我想你可以创建一个包含捕获异常列表的异常并抛出该异常,例如:

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

You can't throw two exceptions.你不能抛出两个异常。 Ie you can't do something like:即你不能做这样的事情:

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

Alternative 1: Exception A is caused by exception B备选方案 1:异常 A 是异常 B引起的

You could nest exceptions using the cause-constructor to do the following:您可以使用原因构造函数嵌套异常以执行以下操作:

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)
}

Good article on chained exceptions: Programming.Guide: Chained Exceptions关于链式异常的好文章: Programming.Guide: Chained Exceptions

Alternative 2: Use suppressed exception备选方案 2:使用抑制异常

One exception can suppress another exception.一个异常可以抑制另一个异常。

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
}

Good article on suppressed exceptions: Programming.Guide: Suppressed Exceptions关于抑制异常的好文章: Programming.Guide: Suppressed Exceptions

I've seen a pattern, where a custom exception internally stores other exceptions (can't remember, why they did it), but it was like:我见过一种模式,其中自定义异常在内部存储其他异常(不记得,他们为什么这样做),但它就像:

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;
  }
}

and it was used like this:它是这样使用的:

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

Later in the code, the container exception was evaluated and dumped to a log file.在代码的后面,容器异常被评估并转储到日志文件中。

Throwing more than a single exception doesn't make sense because you can't have more than a single error (the error can have multiple reasons but there can't be more than a single error at any time).抛出多个异常没有意义,因为您不能有多个错误(错误可能有多种原因,但在任何时候都不能超过一个错误)。

If you need to keep track of the reasons, you can chain exceptions:如果您需要跟踪原因,您可以链接异常:

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

These are available via getCause() .这些可以通过getCause()

To throw multiple exceptions in Java you'll first have to suppress each exception into one customized exception and then throw the same customized exception.要在 Java 中抛出多个异常,您首先必须将每个异常抑制为一个自定义异常,然后抛出相同的自定义异常。 Please check the below code snippet to achieve the same.请检查下面的代码片段以实现相同的目的。

  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;
        }  
    }
}

Call the method addException with the same reference aggExcep wherever you want to(Inside the catch block obviously) suppress any exception.使用相同的引用 aggExcep 在任何你想要的地方(显然在 catch 块内)调用方法 addException 抑制任何异常。 And at the end explicitly throw aggExcep using 'throw' keyword where ever you want to.最后,在您想要的任何地方使用 'throw' 关键字显式地抛出 aggExcep。

The

void addSuppressed(Throwable exception) void addSuppressed(Throwable 异常)

is a predefined method of Throwable class which appends the specified exception to the exceptions that were suppressed in order to deliver this exception.是 Throwable 类的预定义方法,它将指定的异常附加到为了传递此异常而被抑制的异常。

The pattern described by Andreas_D is definitely useful whenever you're handling, say, the server-side compilation of a user-provided file and want to report back the errors. Andreas_D 描述的模式在您处理用户提供的文件的服务器端编译并希望报告错误时绝对有用。

For example, you might have a CompilationException which gets generated if the resource fails to compile.例如,如果资源无法编译,您可能会生成 CompilationException。 Compiling might mean any number of things.编译可能意味着许多事情。 For example, you might evaluate the text inside of a file that an end user uploads, parse out tokens, check for syntax errors and determine whether the file is valid.例如,您可以评估最终用户上传的文件中的文本、解析令牌、检查语法错误并确定文件是否有效。 At the end, the thing is either valid or it is invalid and you want to hand back a proper CompilationException to propagate back up the call stack.最后,该事物要么有效,要么无效,并且您想要交回适当的 CompilationException 以传播回调用堆栈。

Like Andreas describes, you can have an add() method that lets you add compilation issues to your exception.就像 Andreas 描述的那样,您可以使用 add() 方法将编译问题添加到异常中。 Those issues don't have to be Exceptions themselves, but that's up to you.这些问题本身不一定是异常,但这取决于您。 It often helps to stick to a single exception framework so that you can use the same validation logic in multiple places.坚持使用单个异常框架通常会有所帮助,以便您可以在多个地方使用相同的验证逻辑。

At any rate, what you want is a single CompilationException falling back through the call stack because that tells the framework that the thing did not compile.无论如何,您想要的是单个 CompilationException 通过调用堆栈回退,因为它告诉框架该事物未编译。 If anyone up the chain wants to know why, then they can get at the underlying issues with a call to, say, getCauses().如果链上的任何人想知道原因,那么他们可以通过调用 getCauses() 来了解潜在问题。

It's also useful from a UI perspective.从 UI 的角度来看,它也很有用。 That information sticking around on the Exception can be properly handled before going back over the wire so that you can give your end user some information as to why the compilation failed.在通过网络返回之前,可以正确处理留在异常上的信息,以便您可以向最终用户提供有关编译失败原因的一些信息。

You can have the possibility of throwing multiple different exceptions.您可以抛出多个不同的异常。 For example:例如:

if (obj == null)
    throw new NullPointerException();

if (some other case)
    throw new IllegalArgumentException();

if (this == this)
    throw new IOException();

This code may throw multiple different exceptions, but this can never happen at the same time.这段代码可能会抛出多个不同的异常,但这永远不会同时发生。

I am unsure if you are asking whether multiple exceptions can be thrown at a time or we can have a code to handle multiple exceptions at a time.我不确定您是在问是否可以一次抛出多个异常,或者我们可以有一个代码来一次处理多个异常。 I will try to answer both of these.我将尝试回答这两个问题。 This is my first answer on StackOverflow so pardon any errors.这是我在 StackOverflow 上的第一个答案,所以请原谅任何错误。

1) If you want to throw multiple exceptions at a time,I think you can't do that. 1)如果你想一次抛出多个异常,我认为你不能那样做。 Consider an analogous situation.考虑一个类似的情况。 When you are solving a Math questions and reach a point where you are dividing by 0, there is only one error AT THIS POINT of time and that is dividing by zero.当您解决数学问题并达到除以 0 的程度时,此时只有一个错误,即除以零。 So I guess you can just throw one error for a given statement.所以我想你可以只为给定的语句抛出一个错误。 However there can exist many statements in your try catch block each of which might throw a different error.但是,在您的 try catch 块中可能存在许多语句,每个语句都可能引发不同的错误。

2) IF you want to handle/catch multiple errors there are two ways to do it. 2)如果您想处理/捕获多个错误,有两种方法可以做到。 i) Before Java 7: 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) After Java 7,you have the multi catch feature. ii) 在 Java 7 之后,你有多重捕捉功能。

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.
  ...
 }

I believe this will solve your doubt.相信这会解开你的疑惑。 This being my first answer,all suggestions are welcome!这是我的第一个答案,欢迎所有建议!

there is a way for a method to throw mutiple exeptions, but not at one time.有一种方法可以抛出多个异常,但不是一次。 eg when compilation fails for some reason your method can only throw one exception.例如,当由于某种原因编译失败时,您的方法只能抛出一个异常。 if you have to cover different opportunities you might declare you method to throw the parent class of all exceptions "Exception".如果您必须涵盖不同的机会,您可能会声明您的方法来抛出所有异常“异常”的父类。 so, if you declare a method to throw an Exception in general, an exception of any type can be thrown by this method.因此,如果您声明一个通常会抛出异常的方法,则此方法可以抛出任何类型的异常。

for example:例如:

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

i don't know what you actually needed to know but maybe this helps.我不知道你真正需要知道什么,但也许这会有所帮助。 although it has passed a lot of time since your post ^^虽然自从你的帖子已经过去了很多时间^^

greetings你好

Piggybacking on aioobe's answer, what I did was throw each Exception into a list before adding them as suppressed exceptions to a new Exception, then threw the new one:捎带aioobe的回答,我所做的是将每个异常抛出到一个列表中,然后将它们作为抑制异常添加到新异常中,然后抛出新异常:

Example:例子:

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;
}

To avoid an import if you don't already have a List elsewhere, you could also just throw a new Exception instead of initializing a list, add your errors to it with addSuppressed()`` in the catch block, and later call Exception.getSuppressed().length > 0``` to determine if any were added to it, but I just like the list for the readability and the general rationale that I don't want to create an Exception without there actually being an error.如果您在别处还没有 List,为了避免导入,您也可以只抛出一个新的 Exception 而不是初始化列表, addSuppressed()`` in the catch block, and later call使用addSuppressed()`` in the添加您的错误block, and later call Exception。 getSuppressed().length > 0``` 来确定是否添加了任何内容,但我只是喜欢可读性列表和我不想在没有实际错误的情况下创建异常的一般理由。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM