我正在开发一个应用程序,其中流程继续进行,如此UI - >后端流程 - >结果到UI。
在我的代码中,我使用try,catch处理了异常。但是在代码中我有很多重复的异常,可能会在不同的类中抛出相同的异常。
所以,我打算做一个异常处理策略,这样当抛出异常时,它必须被重定向到单独的异常处理代码(类似于单独的自定义异常处理库类)。所以它不应该在我的业务逻辑中。
有人可以建议我如何实现它以及是否最好处理我的异常?或者有人可以建议我除了我以外的其他方法吗?
谢谢,期待你的回复。
答案 0 :(得分:7)
如果你抛出太低级别的异常会抓住上面的几个调用,并打包为更一般和有意义的异常,用户友好的消息出错了,再次将它们抛到最高级别,你停止你的app并以某种方式(例如在标签上)向用户查看它们。
当方法抛出没有的异常时,这是令人不安的 与其执行的任务明显的连接。这经常发生 当方法传播由较低级别引发的异常时 抽象。这不仅令人不安,而且污染了API 更高层的实现细节。如果执行 后续版本中更高层的更改,例外情况 它抛出的东西也会改变,可能会破坏现有的客户 程序
为了避免这个问题,更高层应该捕获较低级别的异常,并且在它们的位置抛出可以解释的异常 在更高层次的抽象方面。这个成语被称为 异常翻译:
// Exception Translation try { // Use lower-level abstraction to do our bidding ... } catch(LowerLevelException e) { throw new HigherLevelException(...); }
虽然异常转换优于低层异常的无意识传播,但不应过度使用。哪里 可能,处理较低层异常的最佳方法是 通过确保较低级别的方法成功来避免它们。有时 你可以通过检查更高级别方法的有效性来做到这一点 将参数传递给较低层之前的参数。
如果不可能防止较低层的异常,那么下一个最好的方法是让更高层静默地解决这些问题 例外,使更高级别方法的调用者与之隔离 较低级别的问题。在这种情况下,它可能是适当的 使用一些适当的日志工具来记录异常,例如 java.util.logging的。这允许管理员调查 问题,同时隔离客户端代码和最终用户。
总之,如果不可能阻止或处理较低层的异常,请使用异常转换,除非较低级别 方法恰好保证其所有异常都是合适的 到更高的水平。链接提供两全其美:它 允许你抛出适当的更高级别的异常 捕获失败分析的根本原因(第63项)。
答案 1 :(得分:6)
来自Effective Java(Joshua Bloch)
避免检查例外情况。
http://www.mindview.net/Etc/Discussions/CheckedExceptions http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html
要理解的一件非常重要的事情是,任何一段代码都会产生异常。 这不是因为方法声明抛出IOException它可能不会抛出任何其他异常。它可以抛出任何其他运行时异常(通用或自定义)。使用已检查的异常,开发人员倾向于反思,并认为捕获IOException将处理所有异常情况,但事实并非如此!
仅限编译时功能
只有编译器会在您忘记捕获或重新抛出已检查的异常时告诉您。在运行时,没有区别。
这意味着通过使用类型擦除技巧,您可以抛出已检查的异常,甚至不需要将其作为方法合同的一部分。
你可以在这里找到这个被称为SneakyTrow的技巧的例子: https://stackoverflow.com/a/4890489/82609
Lombok还提供@SneakyThrow注释来放置方法,这样您就不需要在方法签名中声明已检查的异常。
当您的类客户端可能从异常中恢复时,仅使用已检查的异常。
这是Sun的推荐。
基本上,连接到数据库的尝试将抛出一个已检查的异常,并且重试策略代码将在连接尝试时捕获这些已检查的异常。当超过重试次数时,重试策略将抛出未经检查的异常,这意味着它不是可恢复的异常,因为已经尝试了恢复策略。 顺便说一下,你可以使用Spring RetryTemplate。
避免例外代码
异常类型应足以用于流控制决策。解析异常或流控制只会创建无用的代码。添加更多异常类型,就像你有异常代码一样。
快速失败
让所有不可恢复的异常都抛到IHM层。 如果您使用一个声明已检查异常的框架而您没有恢复策略,请不要犹豫将它们包装到未经检查的异常中。
如果你无法恢复,那么你不应该做“捕获并记录”。或者更糟糕的是,你不应该“捕获并返回null”。这将产生不一致的软件,您可能会在程序中稍后提出另一个异常,但您将无法理解原因。返回null只会在以后创建NullPointerException。
IHM层技术可能有一个异常处理程序/映射器。 Web IHM层具有异常映射器,因此您可以说“此异常会产生404错误”。
功能性方法
有关信息:在函数式语言中,使用异常进行流控制通常被认为是一种不好的做法。 我们通常返回“增强类型”,而不是抛出异常,例如Either [Error,MyResultType]。
返回的实例是错误或成功,成功是返回的MyResultType实例。
流量控制不符合例外情况
创建例外有一个成本(创建堆栈跟踪)。使用if,其他成本远远超过正常流程... 如果可以避免它们,请不要将它们用于流量控制。
基本上,你总是可以避免它们,但在Java中,在某些情况下使用它们进行流量控制有时会更方便。在功能语言中,Either monad再次帮助。
使用断言
如果开发人员假定您的程序中存在某些内容,请使用断言以确保您的断言为真。 看看番石榴的前提条件: https://code.google.com/p/guava-libraries/wiki/PreconditionsExplained
或者您可以使用Java本机断言或某些自定义代码。 这有助于快速失败。