【发布时间】:2010-05-26 11:43:25
【问题描述】:
有没有办法在java中抛出多个异常?
【问题讨论】:
-
不清楚 OP 是要求“在多个异常中抛出一个”还是“同时抛出多个异常”
有没有办法在java中抛出多个异常?
【问题讨论】:
一个方法可以抛出几个异常之一。例如:
public void dosomething() throws IOException, AWTException {
// ....
}
这表明该方法最终可以抛出这两个异常中的一个(以及任何未经检查的异常)。您不能(在 Java 或任何语言 AFAIK 中)同时抛出两个异常,这没有多大意义。
你也可以抛出一个嵌套异常,它包含在另一个异常对象中。但这几乎不能算作“抛出两个异常”,它只是表示由两个异常对象(通常来自不同层)描述的单个异常情况。
【讨论】:
你不能抛出两个异常。 IE。你不能这样做:
try {
throw new IllegalArgumentException(), new NullPointerException();
} catch (IllegalArgumentException iae) {
// ...
} catch (NullPointerException npe) {
// ...
}
您可以使用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
一个异常可以抑制另一个异常。
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
【讨论】:
我想您可以创建一个包含捕获的异常列表的异常并抛出该异常,例如:
class AggregateException extends Exception {
List<Exception> basket;
}
【讨论】:
抛出多个异常是没有意义的,因为您不能有多个错误(错误可能有多种原因,但任何时候都不能有多个错误)。
如果需要跟踪原因,可以链式异常:
} catch (Exception ex) {
throw new RuntimeException("Exc while trying ...", ex);
}
这些可以通过getCause()获得。
【讨论】:
Exception。此外,为了重新打包异常,我使用了一个项目特定的异常基类。通过这种方式,我可以区分可接受的异常、我已经打包并计划处理的异常以及意外异常。
"There were " + errors.size() + " errors:\n" + errors.stream().map(String::valueOf).collect(joining("\n")
我见过一种模式,其中自定义异常在内部存储其他异常(不记得,他们为什么这样做),但它是这样的:
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
}
稍后在代码中,容器异常被评估并转储到日志文件中。
【讨论】:
要在 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 类的预定义方法,它将指定的异常附加到被抑制的异常以传递此异常。
【讨论】:
您可能会抛出多个不同的异常。例如:
if (obj == null)
throw new NullPointerException();
if (some other case)
throw new IllegalArgumentException();
if (this == this)
throw new IOException();
此代码可能会引发多个不同的异常,但绝不会同时发生。
【讨论】:
当您处理用户提供的文件的服务器端编译并想要报告错误时,Andreas_D 描述的模式绝对有用。
例如,如果资源编译失败,您可能会生成 CompilationException。编译可能意味着很多事情。例如,您可以评估最终用户上传的文件中的文本、解析令牌、检查语法错误并确定文件是否有效。最后,这个东西要么是有效的要么是无效的,你想交回一个适当的 CompilationException 来传播回调用堆栈。
正如 Andreas 所描述的,您可以使用 add() 方法将编译问题添加到您的异常中。这些问题本身不一定是异常,但这取决于您。坚持使用单一异常框架通常会有所帮助,这样您就可以在多个地方使用相同的验证逻辑。
无论如何,您想要的是通过调用堆栈回退的单个 CompilationException,因为这会告诉框架该事物未编译。如果链条上的任何人想知道原因,那么他们可以通过调用 getCauses() 来解决根本问题。
从用户界面的角度来看,它也很有用。在通过网络返回之前,可以正确处理保留在异常上的信息,以便您可以向最终用户提供一些关于编译失败原因的信息。
【讨论】:
我不确定您是在询问是否可以一次抛出多个异常,或者我们可以有一个代码来一次处理多个异常。我将尝试回答这两个问题。这是我在 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.
...
}
我相信这会解决您的疑问。 这是我的第一个答案,欢迎所有建议!
【讨论】:
有一种方法可以抛出多个异常,但不是一次。例如当由于某种原因编译失败时,您的方法只能抛出一个异常。 如果你必须涵盖不同的机会,你可以声明你的方法来抛出所有异常“异常”的父类。 所以,一般来说,如果你声明一个抛出异常的方法,这个方法可以抛出任何类型的异常。
例如:
public static void main(String[] args) throws Exception
{
getClipboard(); // throws an UnsupportedFlavorException
initIOActivity(); // throw an IOException
}
我不知道您实际需要知道什么,但也许这会有所帮助。 虽然距离你的帖子已经过去了很多时间^^
问候
【讨论】:
public void method() throws UnsupportedSomethingException, IOException {...}。使用Exception 本身是一种快速的方法,可以让你从正确处理异常中获得大量权力。我只建议在 UI 线程或某个顶层捕获异常,以避免完全崩溃。
捎带 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``` 来确定是否添加了任何内容,但我只是喜欢该列表的可读性和一般理由,即我不想在没有实际错误的情况下创建异常。
【讨论】: