我有一个项目,我必须解析格式化的ASCII数据。解析器可能会识别何时出现格式问题(预计未找到,发现意外数据)。通常情况下,如果我发现一些失败,我会抛出异常。但是,这一次,我想继续解析过程,并将解析器错误存储在结束类中。我的问题是,创建一个新的异常并将其存储在List中而不是抛出它以便不停止处理可以吗?当我创建一个新的异常时,我必须抛出它还是可以将它放入List中?
回答
你可以做到以下几点:
- 店的问题
List
(字符串的邮件列表,例如,或者包含问题细节的特定对象的列表)到底 - ,如果列表不为空,抛出具有列表
例如自定义异常:
List<ParsingProblem> problems = new ArrayList<ParsingProblem>();
while (parsing) {
...
problems.add(new ParsingProblem("some message", someRelevantValue));
}
if (!problems.isEmpty()) {
throw new ParsingException(problems);
}
如果您不想中止处理(即您可以在本地处理问题),则不应使用异常。创建一个异常,但不抛出它是不是一个好主意(它是相当昂贵的,它不是“主流”,所以它使你的代码更难理解和使用)。
最好是创建例如一个错误消息字符串并将其存储在问题列表中。或者,如果您需要存储更多结构化的错误信息,请为其创建一个自定义类。
我的问题是,可以创建一个新的异常,只是将它存储在一个列表中,而不是抛出它不停止处理?
是的。那可行。但是,这是相当昂贵的,因为Exception对象捕获当前线程的所有堆栈帧。如果你不打算使用堆栈框架并且不打算抛出异常,那么你做了很多不必要的工作。除非有一个特定的原因,你需要必须使用Exception
,那么捕捉错误细节的简单类是一个更好的主意。
但是,您可以使用巧妙的技巧/技巧使实例化的异常对象更便宜。如果您查看Throwable
API,您会注意到有一种方法称为fillInStackTrace()
。该方法由Throwable
构造函数本身调用来捕获堆栈帧,并且实现(在Throwable
中)在某些本机代码中执行此操作。但是,此方法不是final
,因此您可以在自定义异常类中重写它以将其变为无操作。
瞧!构造函数运行速度更快!但是,当然,如果你需要一个堆栈跟踪来处理异常情况,那么你运气不好。所以我建议非常谨慎地使用这个黑客技巧。
您可以覆盖'fillInStackTrace()'以避免总是支付这笔费用。我不确定'Throwable'的构造函数是否调用'fillInStackTrace()'。 – jmg 2011-04-04 10:32:15
@jmg ...我到了那里。 – 2011-04-04 10:35:37
@Stephen C:当'fillInStackTrace()'被覆盖时,你并不一定缺乏。可以使用'super.fillInStackTrace()'从'public void reallyFillInStackTrace(){super.fillInStackTrace(); }'。 – jmg 2011-04-04 10:37:57
语言或JVM规范中的任何内容都不会强制您抛出Exception
,您可以像处理Java中的其他任何Object
一样处理它。所以是的,从这方面来说,保留一个Exception
对象的列表是完全正确的。
但是,这是一件很不寻常的事情。我本不会把它称为一个糟糕的设计,但它有点奇怪的气味。
也许你能避免这个问题,通过创建一个Problem
,并保持在一个List
(和您的自定义Exception
添加这样的对象)。
- 1. Info.plist关键字符串 - 在SDK中定义,还是我必须创建它们?
- 2. 当我不知道它可能抛出的位置时,如何记录异常?
- 3. 抛出一个异常,捕获它
- 4. Bootstrap CSS和JS我必须将它们包含在单独的文件中还是可以编译它们?
- 5. 转换为List()抛出异常对象必须实现IConvertible
- 6. 当我创建一个新的字符时,std :: bad_alloc被抛出**
- 7. Android DialogFragment:我可以重新使用,还是必须重新使用另一个?
- 8. StructureMap认为它必须注入构造函数并抛出异常
- 9. 抛出一个新的异常抛出一个旧的异常
- 10. 创建c#异常而不是抛出它
- 11. 我是否必须创建一个新的数据库?
- 12. 抛出异常后我必须打破吗?
- 13. 试图更新XML的节点值,它抛出一个异常
- 14. 抛出异常:封装它们还是不封装?
- 15. ServerSocket.close()。它什么时候抛出异常?
- 16. 当我加载的另一个AppDomain抛出一个未处理的异常时,我可以将我当前的AppDomain从拆除状态中分离出来吗?
- 17. 当我抛出一个异常时,内存发生了什么?
- 18. 当我使用Injector.get时发生一个服务抛出异常()
- 19. 新手:抛出新的异常 - 我们可以更改异常名称吗?
- 20. java LocalDate Datatype,如果我必须从2D数组输入参数到LocalDate,它会抛出异常
- 21. 当我创建一个新的组织时,GitHub抛出我找不到页面
- 22. 我必须创建一个96列的表格。它是否有效?但96列必须在表
- 23. 它是很好的参照抛出一个异常对象
- 24. Powershell:创建并抛出新的异常
- 25. 使我的viewModel工作,它必须是一个列表
- 26. Coldfusion 9上的EHCache - 我可以创建多个缓存还是禁用它?
- 27. 当我从C#调用存储过程时,它会抛出异常
- 28. 当db中的值为null时,我可以配置NHibernate抛出异常吗?
- 29. 我必须投入一个`u8`才能将它用作向量中的索引?
- 30. 我可以缩短这个吗?在vb.net中创建一个进程 - 必须调用它4次
我不会使用这个类的名称错误。 (原因,从你的构造函数来看,我假设你不是指'java.lang.Error')。 – aioobe 2011-04-04 10:29:20
@aioobe yesh,它不是java.lang.Error。我会选择另一个名字。实际上,我已经看到这种情况下的类确实被称为'错误',但也许不太合适。 – Bozho 2011-04-04 10:31:21
这是一个相当明确的方式,我相信。坦率地说,我自己应该想到这个,但由于某种原因,我的头因为例外而停滞不前。 – JRSofty 2011-04-04 12:29:59