梅州市建设培训中心网站,网站建设费用大概多少钱,无极招聘信息,asp网站目录权限最近#xff0c;我与一个朋友进行了讨论#xff0c;他是一个相对初级但很聪明的软件开发人员。 她问我有关异常处理的问题。 这些问题指出了一种技巧和窍门#xff0c;肯定有它们的清单。 但是我坚信我们编写软件的方式背后的背景和动机#xff0c;因此我决定从这种角度写关… 最近我与一个朋友进行了讨论他是一个相对初级但很聪明的软件开发人员。 她问我有关异常处理的问题。 这些问题指出了一种技巧和窍门肯定有它们的清单。 但是我坚信我们编写软件的方式背后的背景和动机因此我决定从这种角度写关于异常的想法。 编程中的异常使用Java作为故事的舞台用于通知我们在执行代码期间发生了问题。 异常是类的特殊类别。 使它们与众不同的是它们扩展了Exception类而后者又扩展了Throwable类。 作为Throwable的实现我们可以在必要时“抛出”它们。 那么如何发生异常 异常类的实例从JVM或使用throw语句在代码段中引发。 那是怎么回事但是为什么呢 我敢肯定当我们看到异常发生时我们大多数人都会畏缩但这是使我们受益的工具。 在引发异常之前返回了特殊值或错误代码以使我们知道操作没有成功。 忘记或不知道检查此类错误代码可能会导致我们的应用程序发生不可预测的行为。 所以对 在我撰写以上内容时我想到了两件事。 异常是一个不好的事件因为创建异常时我们知道发生了问题。 异常是一种有用的构造因为异常可以为我们提供有关发生错误的有价值的信息并允许我们针对每种情况采取适当的行为。 试图散布此设计问题的实质 触发方法/请求执行某项操作但它可能会失败–我们如何最好地通知调用方它失败了 我们如何传达有关发生的情况的信息 我们如何帮助客户决定下一步该怎么做 使用异常的问题在于我们“放弃了”而不仅仅是“放弃”。 我们以“爆炸性”的方式来做我们服务的客户/呼叫者必须处理混乱 。 因此关于异常是我的第一个建议因为它们是一件坏事请尽量避免 。 在您所控制的软件部分中实施难以出错的设计。 您可以使用支持此行为的语言功能。 我相信Java中最常见的异常是NullPointerException而Optionals可以帮助我们避免它们。 让我们考虑一下我们想要检索具有指定id的雇员 public OptionalEmployee tryGetEmployee(String employeeId) {return Optional.ofNullable(employeeService.getEmployee(employeeId));
} 现在好多了。 但是除了语言的功能之外我们还可以通过某种方式设计代码以免发生错误。 如果我们考虑一种只能接收正整数作为输入的方法则可以设置代码这样客户端就极不可能错误地传递无效输入。 首先我们创建一个PositiveInteger类 public class PositiveInteger {private Integer integerValue;public PositiveInteger(Integer inputValue) {if(inputValue 0) {throw new IllegalArgumentException(PositiveInteger instances can only be created out of positive integers);}this.integerValue inputValue;}public Integer getIntegerValue() {return integerValue;}
} 然后对于只能使用正整数作为输入的方法 public void setNumberOfWinners(PositiveInteger numberOfWinners) { … } 这些当然是简单的例子我确实认为问题的核心是偶尔发生问题然后我们必须告知客户发生的情况。 假设我们从外部后端系统检索了一个员工列表那么事情可能会出错。 如何处理呢 我们可以将响应对象设置为GetEmployeesResponse如下所示 public class GetEmployeesResponse {private Ok ok;private Error error;…class Ok {private ListEmployee employeeList;...}class Error {private String errorMessage;...}
} 但是让我们成为现实主义者您无法控制代码库的每个部分也不会更改所有内容。 确实会发生异常因此让我们从它们的简要背景信息开始。 如前所述Exception类扩展了Throwable类。 所有异常都是异常类的子类。 可以将异常分为已检查和未检查的异常。 这仅表示某些异常已检查的异常要求我们在编译时指定在异常发生时应用程序的行为方式。 未检查的异常不要求我们进行编译时间处理。 要创建此类异常您可以扩展RuntimeException类该类是Exception的直接子类。 关于已检查与未检查的较旧且常见的指导原则是运行时异常用于表示应用程序通常无法预期或从中恢复的情况而已检查异常是编写良好的应用程序应从中预期并从中恢复的情况。 好吧我主张仅使用运行时异常 。 而且如果我使用的库具有带有检查异常的方法那么我将创建一个包装器方法将其转换为运行时。 那为什么不检查异常呢 Bob叔叔在他的“ Clean Code”一书中指出 它们违反了Open / Closed原理 因为使用新的throws声明更改签名可能会对调用该方法的程序的各个级别产生影响。 现在无论是检查还是未检查由于异常是一种结构可让我们洞悉出了什么问题因此应该对所发生的事情尽可能地具体和丰富 。 因此 尝试使用标准异常其他人将更容易理解发生的情况。 看到NullPointerException时任何人都清楚原因。 如果您自己设置例外请使其明智且具体。 例如ValidationException使我知道某个验证失败AgeValidationException使我指出特定的验证失败。 具体而言既可以更轻松地诊断发生了什么又可以根据发生的事情异常类型指定不同的行为。 这就是为什么您必须始终首先捕获最具体的异常的原因 因此这里出现了另一个常见建议指示不要抓住“异常”。 这是一个有效的建议我偶尔不遵循。 在我的api的边界比如说我的REST服务的端点中我总是有通用的catch Exception子句。 我不希望任何意外以及我在代码中无法预测或防范的事情可能会向外界揭示事物。 具有描述性但也可以根据抽象级别提供例外 。 考虑创建一个异常层次结构以不同的抽象级别提供语义信息。 如果从程序的较低层引发了异常例如与数据库相关的异常则不必向API的调用者提供详细信息。 捕获异常并引发一个更抽象的异常该异常仅通知调用者其尝试的操作失败。 似乎这与“仅在可能的情况下才捕获”的常见方法背道而驰但事实并非如此。 只是在这种情况下我们的“处理”是触发新异常。 在这些情况下通过将原始异常传递给新异常的构造函数可以使整个异常历史在抛出之间可用。 “手柄”一词已被多次使用。 这是什么意思 当异常在我们熟悉的catch子句中被“捕获”时被视为已处理。 引发异常时首先它将在发生异常的代码中搜索异常处理如果未找到异常它将进入所包含方法的调用上下文依此类推直到找到异常处理程序或程序为止将终止。 我再次喜欢Bob叔叔的一件好事就是try-catch-finally块定义了程序中的作用域。 除词汇范围外我们还应考虑其概念范围将try块视为事务 。 如果出问题了该怎么办 我们如何确保使程序保持有效状态 不要忽略例外 我猜程序员对许多小时的不满是由无声异常引起的。 捕获并最终阻止是您进行清理的地方。 确保等待直到掌握了正确处理异常的所有信息为止。 这可以与早起早发的原则联系在一起。 我们提早抛出因此我们不必进行由于异常而不得不稍后恢复的操作而为了及时掌握所有信息以正确处理异常我们就可以迟到。 顺便说一句当您捕获异常时只有在解决它们时才记录日志否则单个异常事件会导致日志混乱。 最后对于异常处理我个人更喜欢创建一个可以在代码的不同部分中使用的错误处理服务 并在日志记录重新抛出清理资源等方面采取适当的措施。它集中了我的错误处理行为避免了代码重复并帮助我从更高级的角度了解应用程序中如何处理错误。 因此既然我们有了足够的上下文悖论规则及其例外我们可以总结一下 尽量避免例外。 使用语言功能和适当的设计以实现它 使用运行时异常将方法与检查的异常包装在一起然后将其转换为运行时 尝试使用标准例外 使您的例外情况具有特定性和描述性 首先捕获最具体的异常 不要赶上异常 但是要在api的边界上抓住Exception。 完全掌控一切 创建与应用程序的层和功能相匹配的异常层次结构 在适当的抽象级别上抛出异常。 逐层移动时捕获异常并引发更高级别的异常 通过在新的构造函数中提供异常在重新抛出时传递完整的异常历史记录 将try-catch-finally块视为事务。 当出现问题时请确保将程序保持在有效状态 在可以处理时捕获异常 永远不要有空的catch子句 处理异常时记录 拥有全局异常处理服务并具有如何处理错误的策略 就是这样 继续前进成为非凡 翻译自: https://www.javacodegeeks.com/2017/12/how-to-deal-with-exceptions.html