立即包装和抛出异常以提供更多关于抛出异常的上下文/原因是否有意义?
例如,假设CustomException
是特定应用程序/模块的自定义异常:
throw new CustomException(new UnsupportedOperationException("Feature X is no longer supported. :("));
简单地选择一个或另一个更标准吗?例如:
throw new CustomException("Feature X is no longer supported. :(");
或
throw new UnsupportedOperationException("Feature X is no longer supported. :(");
我理解,如果它们被重新抛出/来自catch块,则抛出包装异常是相当标准的做法,但我认为我没有看到从头开始抛出包装异常(使用new
)。 / p>
答案 0 :(得分:1)
立即包装和抛出异常以提供更多关于抛出异常的上下文/原因是否有意义?
当您捕获异常并将其包装起来时,这非常有意义。添加上下文信息是执行此操作的一个原因。另一个原因是为了使它适合你的 API的调用者(而不是适合你的API实现),使它成为一种不同类型的例外。
考虑一个示例:您的库使用RDBMS后端来存储一些数据,并启用了引用完整性约束。其中一个约束可能会拒绝同一用户ID的某种重复记录。在这种情况下,您的库将捕获SQLException
,表示违反了参照完整性约束。但是,您的库不应向其用户抛出SQLException
。相反,它应该抛出一个自定义DuplicateUserRecordException
,其中包含用户ID和SQLException
。
然而,创建一个异常,另一个异常嵌套在内部(即按字面意思执行你的第一个例子)并不是一个好主意。将异常包装在另一个异常中而不是提供不相关的异常的主要原因是保留抛出异常的位置。但是,永远不会抛出嵌套异常,因此它内部没有嵌入有用的上下文。
答案 1 :(得分:1)
对于你的情况我会说
throw new CustomException("Feature X is no longer supported. :(");
除非你想让顶级组件知道你在扔什么。 这可以是
1. DAO related
2. Any exception would cause another exception
3. multiple exception would occur
例如,如果您的此功能X可能会抛出IOException和FileNotFoundException。你不想将两者都返回到上部组件然后你应该包装它。但是你知道功能X对调用者类没有任何影响,那么你可以用自定义异常结束它。
答案 2 :(得分:1)
我无法想到创建这样的包装异常是一个好主意。
填充堆栈跟踪相对昂贵,并且创建重复的堆栈跟踪是一种浪费。
异常链接和抑制异常主要用于记录;检查此信息以控制流量的应用程序是脆弱的。您要传达的任何额外信息都可以放在消息中,以便使用堆栈跟踪进行记录。
异常机制基于异常类型,处理程序应主要依赖于流控制。如果需要其他信息,可以通过特定API在自定义异常中公开。
对于弃用的API,抛出UnsupportedOperationException
是最佳选择。将库升级到不兼容的版本是一个编程错误。这在运行时不会出现不可预测的情况;开发人员可以而且应该在开发期间发现此问题。
如果捕获了运行时异常,则应该在应用程序中处于高级别。例如,Servlet引擎可能会捕获并报告运行时错误,而不会中止整个过程,从而保护其他应用程序。 GUI可能会捕获事件调度引起的运行时异常,而不会导致整个应用程序崩溃。
在其他情况下,抛出新的CustomException
可能会更好。 CustomException
的子类可用于报告可能可恢复的错误类型。例如,假设用户名必须是唯一的。您的应用程序可以检查是否已使用用户名,然后在名称可用时创建帐户,但这会引入竞争条件,其中另一个用户可能在此期间声明该名称。通过乐观地尝试创建用户帐户,如果用户名不可用,则使用特定DuplicateUsernameException
失败,处理程序可以提示输入新用户名。