我有一些模块,每个模块都包含一些模型,我想从持久文件中解析它。
当我读取文件时,我不知道哪个模块能够解析它,这就是我尝试用我的第一个模块的解析器解析它的原因。如果失败,我尝试使用第二个模块的解析器并继续,直到我尝试了所有解析器。 解析器可以以多个异常(Exception类的不同子类型)或解析的模型对象(ModelBase类的不同子类型)的形式提供信息。
如果解析器都没有成功,我想将所有给定的异常包装成一个大的Exception,抛出它并在我的应用程序代码中以某种形式捕获它(以新的大异常形式),我可以在那里处理问题(例如向用户显示所有解析问题和堆栈跟踪,以某种方式处理它们等。)。
我的伪代码:
ModelBase getModelOrBigException(File file)
throws MyBigException {
List<Exception> exceptions = new ArrayList<>();
for (Module module : myModules){
try {
ModelBase model = module.parse(file);
return model;
}
catch (ParsingException1 p1) { exceptions.add(p1); }
catch (ParsingException2 p2) { exceptions.add(p2); }
}
throw new MyBigException(exceptions);
}
我想调用代码
void openFilesHandler(){
//... selecting file
try {
process(getModelOrBigException(file));
} catch (MyBigException e) {
// process the sub-exceptions or show them to user or print stacktraces of all sub-exceptions or show sub-exceptions by type etc
}
}
显然,如果我捕获MyBigException,我将无法在默认情况下调用getStackTrace(),getMessage(),getLocalizedMessage()等方法,只有在我实现类似于此的异常类时才会这样:
class MyBigException extends Exception {
public MyBigException(Exception e1, Exception e2, ..., Exception eN){
super(e1, e2, ..., eN); // This is not possible, only one argument is acceptable
}
}
或者这个:
class MyBigException extends Exception {
List<Exception> exceptions = new ArrayList<>();
public MyBigException(List<Exception> exceptions){
super(exceptions); // This is not possible, list or array of exceptions is not allowed here
}
}
问题:
我应该如何创建一种新的Exception类型,它可以在支持原始Exception类的方法的情况下存储多个异常? 当我这样做时:
myBigException.printStackTrace();
或者这个:
myBigException.getMessage();
我想打印/获取所有存储异常的所有堆栈跟踪。 我应该将所有给定的例外传递给super()方法吗?
有没有比上述解决方案更好的方法来解析解决方案?
答案 0 :(得分:3)
我想打印/获取所有存储异常的所有堆栈跟踪。我是不是该 将所有给定的异常传递给super()方法?
如果您想要打印所有堆栈跟踪或异常消息,那么您几乎就在那里,您需要添加更多位,如下所述:
(1)在MyBigException
内,创建一个构造函数MyBigException(List<Exception> exceptions, String exeptionMessage)
并调用super(exeptionMessage);
(2)覆盖printStackTrace()
中的MyBigException
并迭代List<Exception>
并在每个异常对象上调用printStackTrace()
。
您可以参考以下代码:
MyBigException
课程:
public class MyBigException extends Exception {
private List<Exception> exceptions = new ArrayList<>();
public MyBigException(List<Exception> exceptions, String exeptionMessages){
//call super and pass message
super(exeptionMessages);
this.exceptions = exceptions;
}
public void printStackTrace() {
for(Exception exception : exceptions) {
exception.printStackTrace();
}
}
}
getModelOrBigException()
代码:
ModelBase getModelOrBigException(File file)
throws MyBigException {
List<Exception> exceptions = new ArrayList<>();
//Capture exception messages as well using StringBuilder
StringBuilder exceptioMessages = new StringBuilder();
for (Module module : myModules){
try {
ModelBase model = module.parse(file);
return model;
}
catch (ParsingException1 p1) {
exceptions.add(p1);
exceptioMessages.append("YOUR MESSAGE FOR ParsingException1;");
}
catch (ParsingException2 p2) {
exceptions.add(p2);
exceptioMessages.append("YOUR MESSAGE FOR ParsingException2;");
}
}
throw new MyBigException(exceptions, exceptioMessages.toString());
}
答案 1 :(得分:1)
我想到了两个选择。
使用addSuppressed
来抑制给定的异常。然后,您可以稍后使用getSuppressed()
再次检索它。这也是用于try-with-resources-statements抛出异常的机制。这样,myBigException
的堆栈跟踪也会自动显示被抑制的跟踪。
为您的异常类内部列表添加一个访问器方法,以便您可以从外部访问它,例如getExceptions()
。但是,您需要自己处理每个异常的堆栈跟踪。您可以覆盖printStackTrace(*)
方法,但这对我来说似乎是开销。
它主要取决于您想要实现的目标(或更合适的内容)以及您希望以后如何访问异常。
您可能还希望在第二种情况下提供自己的printStackTraces()
方法,或在两种情况下覆盖getMessage()
- 方法,以提供更合适的消息。
答案 2 :(得分:1)
BigException
的原因不能包含很多例外情况。抛出一个异常,它会一直向上移动,直到你处理它为止。您可以将其添加到因果关系链中,这就是Exception
的构造函数接受另一个异常作为此异常的原因的原因。
但是在你的情况下,在抛出许多解析异常并且已经处理(通过将它们添加到列表中)后,你抛出BigException
。
因此,链中的第一个例外实际上是BigException
。如果我是你,我只需要获取解析异常列表的getter并使用该列表,即通知用户,记录列表等。