java 示例_功能Java示例 第3部分–不要使用异常来控制流程

java 示例

这是称为“ Functional Java by Example”的系列文章的第3部分。

我在本系列的每个部分中开发的示例是某种“提要处理程序”,用于处理文档。 在前面的部分中,我从一些原始代码开始,并应用了一些重构来描述“什么”而不是“如何”。

为了帮助代码向前发展,我们需要摆脱好的java.lang.Exception (免责声明:我们实际上无法摆脱它)这就是其中的内容。

如果您是第一次来这里,最好从头开始阅读。 它有助于了解我们从何处开始以及如何在整个系列中继续前进。

这些都是这些部分:

  • 第1部分–从命令式到声明式
  • 第2部分–讲故事
  • 第3部分–不要使用异常来控制流程
  • 第4部分–首选不变性
  • 第5部分–将I / O移到外部
  • 第6部分–用作参数
  • 第7部分–将失败也视为数据
  • 第8部分–更多纯函数

我将在每篇文章发表时更新链接。 如果您通过内容联合组织来阅读本文,请查看我博客上的原始文章。

每次代码也被推送到这个GitHub项目 。

快速了解异常

自Java 1.0以来,我们的java.lang.Exception就已经存在了-基本上在好时机和其他时候成为我们的敌人。

关于它们的讨论不多,但是如果您想阅读一些资源,这是我的最爱:

  • Java异常 (JavaWorld)
  • Java例外– GeeksforGeeks (geeksforgeeks.org)
  • 9种处理Java异常的最佳实践 (stackify.com)
  • 异常处理的最佳实践 (onjava.com)
  • Java异常面试问答 (journaldev.com)
  • 带有示例的Java中的异常处理 (beginnersbook.com)
  • Java异常处理(Try-catch) (hackerrank.com)
  • 十大Java异常处理最佳实践– HowToDoInJava (howtodoinjava.com)
  • Java中的异常处理和断言– NTU (ntu.edu.sg)
  • 异常处理:最佳实践指南 (dzone.com)
  • 在Java中处理异常的9种最佳实践 (dzone.com)
  • 修复7个常见Java异常处理错误 (dzone.com)
  • Java惯例->检查与未检查异常 (javapractices.com)
  • Java中异常的常见错误 MikaelStåldal的技术博客 (staldal.nu)
  • Java开发人员在使用异常时犯的11个错误 (medium.com/@rafacdelnero)
  • 检查异常是好是坏? (JavaWorld)
  • 检查异常:Java的最大错误 精简Java (literatejava.com)
  • 未经检查的异常-争议 (docs.oracle.com)
  • 已检查的异常问题 (artima.com)
  • Java例外:您(可能)做错了 (dzone.com)
  • Java理论与实践:异常辩论– IBM (ibm.com)
  • Java的检查异常是一个错误(这是我想做的 (radio-weblogs.com)
  • Buggy Java代码:Java开发人员最常犯的10个错误 Toptal (toptal.com)

您已经在Java 8上了吗? 生活变得好多了! 我… 呃…哦,等等。

  • Java输入流的错误处理– Javamex (javamex.com)
  • 在Java流中处理检查的异常 (oreilly.com)
  • JDK 8流中的异常处理 (azul.com)
  • 带有异常的Java 8功能接口 (slieb.org)
  • 重新打包流中的异常– blog @ CodeFX (blog.codefx.org)
  • 如何在Java 8 Stream中处理异常? –堆栈溢出 (stackoverflow.com)
  • 检查异常和流| Benji的博客 (benjiweber.co.uk)
  • 一个关于检查异常和Java 8 Lambda表达式的 故事 (javadevguy.wordpress.com)– 很好的战争故事!
  • hgwood / java8-streams-and-exceptions (github.com)

好的,看来您不可能正确地做到这一点。

至少,阅读上述名单后,我们现在完全取决于对速度的话题��

幸运的是,我不必再写一篇博客文章,介绍上面的文章已经涵盖了95%的内容,但是在这里,我将重点介绍代码中实际存在的一个Exception ��

副作用

既然您正在阅读这篇文章,您可能会对为什么这一切都与函数式编程有关感兴趣。

在以更“实用的方式”处理代码的过程中,您可能会遇到“副作用”一词,这是一件“坏事”。

在现实世界中, 副作用是您不希望发生的事情 ,您可能会说它等同于“例外”情况(您会例外地指出),但是在函数式编程上下文中它具有更严格的含义。

维基百科有关副作用的文章说:

副作用(计算机科学)在计算机科学中,如果函数或表达式在返回范围之外修改了某些状态或与其调用函数或外界有可观察的交互作用,则称其为副作用。 …在函数式编程中,很少使用副作用。

因此,在本系列的前两篇文章之后,让我们看看我们的FeedHandler代码当前的样子:

class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {changes.findAll { doc -> isImportant(doc) }.each { doc ->try {def resource = createResource(doc)updateToProcessed(doc, resource)} catch (e) {updateToFailed(doc, e)}}}private Resource createResource(doc) {webservice.create(doc)}private boolean isImportant(doc) {doc.type == 'important'}private void updateToProcessed(doc, resource) {doc.apiId = resource.iddoc.status = 'processed'documentDb.update(doc)}private void updateToFailed(doc, e) {doc.status = 'failed'doc.error = e.messagedocumentDb.update(doc)}}

在一个地方,我们尝试捕获异常,在那儿,我们循环浏览重要的文档,并尝试为其创建“资源”(无论是什么)。

try {def resource = createResource(doc)updateToProcessed(doc, resource)
} catch (e) {updateToFailed(doc, e)
}

在上面的代码中catch (e)是Groovy catch (Exception e)简写catch (Exception e)

是的,这就是我们正在捕获的通用java.lang.Exception 。 可以是任何例外,包括NPE。

如果createResource方法没有引发任何异常,则将文档(“ doc”)更新为“已处理”,否则将其更新为“失败”。 顺便说一句,即使updateToProcessed也会引发异常,但是对于当前的讨论,我实际上只对成功创建资源感兴趣。

因此,上面的代码可以工作 (我已经通过单元测试来证明它:-)),但是我对try-catch语句不满意。 我只对成功创建资源感兴趣,而且很傻,我只能提出createResource来返回成功的资源引发异常。

抛出异常以表示出了点问题,躲开闪避,让调用者捕获该异常以进行处理,这是为什么发明了异常的原因呢? 而且比返回null更好吗?

它一直在发生。 采取一些我们最喜欢的框架,例如JPA规范中的 EntityManager#find

啊! 返回null

返回值:
找到的实体实例;如果该实体不存在,则返回null

错误的例子。

函数式编程鼓励使用无副作用的方法(或函数),以使代码更易于理解且更易于推理。 如果某个方法仅接受某些输入并每次都返回相同的输出(这使其成为一个函数),则各种优化都可以在后台进行,例如通过编译器或缓存,并行化等。

我们可以再次用函数的(计算出的)值代替函数,这称为参考透明度 。

在上一篇文章中,我们已经将一些逻辑提取到了自己的方法中,例如下面的isImportant 。 给定相同的文档(具有相同的 type属性)作为输入,我们每次都会得到相同的 (布尔值)输出。

boolean isImportant(doc) {doc.type == 'important'
}

这里没有可观察到的副作用,没有全局变量被突变,没有日志文件被更新–它只是塞进,塞出

因此,我想说的是,通过我们的传统异常与外界交互的函数很少在函数式编程中使用。

我想做得更好更好

救援可选

正如石磊韦伯表示它:

关于如何在Java中有效使用异常有不同的观点。 有些人喜欢检查异常,有些人则认为这是一次失败的实验,他们更喜欢独占使用未检查异常。 其他人则完全避开异常,而赞成传递和返回诸如Optional或Maybe之类的类型。

好的,让我们尝试一下Java 8的Optional以便发出是否可以创建资源的信号。

让我们更改我们的webservice接口和createResource方法,以在Optional包装并返回我们的资源:

//private Resource createResource(doc) {
private Optional<Resource> createResource(doc) {webservice.create(doc)
}

让我们更改原始的try-catch

try {def resource = createResource(doc)updateToProcessed(doc, resource)
} catch (e) {updateToFailed(doc, e)
}

map (处理资源)和orElseGet (处理空的可选):

createResource(doc).map { resource ->updateToProcessed(doc, resource)}.orElseGet { /* e -> */updateToFailed(doc, e)}

很棒的createResource方法:返回正确结果,或者为空结果。

等一下! 唯一的例外e我们需要传递到updateToFailed走了 :我们有一个空的Optional替代。 我们不能存储的原因失败的原因 -这是我们做的必要性。

可能是Optional只是表示“缺席”,并且是我们此处目的不正确的工具。

出色的完成

如果没有try-catchmap-orElseGet ,我确实喜欢代码开始更多地反映操作“流程”的方式。 不幸的是,使用Optional更适合“得到某事”或“一无所获”(也建议使用诸如maporElseGet类的名称),并且没有给我们提供记录失败原因的机会。

还有什么其他方法可以取得成功的结果或得出失败的原因,同时仍然可以接近我们的阅读方式呢?

Future 。 更好的是: CompletableFuture

CompletableFuture (CF)知道如何返回值,这类似于Optional 。 通常,CF用于将来获取值 ,但这不是我们想要将其用于…的原因。

从Javadoc :

……支持……在完成时触发的行动的未来。

跳动,它可以表示“异常”完成 -给我机会对其采取行动。

让我们更改maporElseGet

createResource(doc).map { resource ->updateToProcessed(doc, resource)}.orElseGet { /* e -> */updateToFailed(doc, e)}

thenAccept (处理成功)并exceptionally (处理失败):

createResource(doc).thenAccept { resource ->updateToProcessed(doc, resource)}.exceptionally { e ->updateToFailed(doc, e)}

CompletableFuture#exceptionally方法接受一个带有我们实际失败原因的异常e的函数。

您可能会想: tomayto,tomahto。 首先,我们进行了try-catch然后我们进行了thenAccept-exceptionally ,那么有什么大不同?

好吧,我们显然不能摆脱特殊情况,但我们现在正在像Functionalville的居民一样思考:我们的方法开始成为函数 ,告诉我们有什么东西有事。

考虑到这是我们需要对第4部分进行的一次小型重构,而在第5部分中,我们将限制更多的代码副作用。

现在就这样

作为参考,这是重构代码的完整版本。

class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {changes.findAll { doc -> isImportant(doc) }.each { doc ->createResource(doc).thenAccept { resource ->updateToProcessed(doc, resource)}.exceptionally { e ->updateToFailed(doc, e)}}}private CompletableFuture<Resource> createResource(doc) {webservice.create(doc)}private boolean isImportant(doc) {doc.type == 'important'}private void updateToProcessed(doc, resource) {doc.apiId = resource.iddoc.status = 'processed'documentDb.update(doc)}private void updateToFailed(doc, e) {doc.status = 'failed'doc.error = e.messagedocumentDb.update(doc)}}

-

翻译自: https://www.javacodegeeks.com/2018/01/functional-java-example-part-3-dont-use-exceptions-control-flow.html

java 示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/334098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win7 计算机定时关机脚本,win7怎么定时关机?win7定时关机设置两种方法

当我们在操作电脑的时候&#xff0c;有时会有需要定时关机&#xff0c;或者不在电脑前操作是需要过段时间自动关机&#xff0c;但是Win7系统没有自带的定时关机软件&#xff0c;很多电脑用户又不喜欢安装第三方软件来完成该操作。那么win7怎么定时关机&#xff1f;本文为大家介…

java面试spring_针对Java程序员的二十大Spring REST面试问题答案

java面试spring大家好&#xff0c;过去两周来&#xff0c;我一直在与Spring教程共享一些REST&#xff0c;今天&#xff0c;我将向申请Web开发人员角色的Java开发人员共享一些常见的Spring和REST采访问题。 由于Spring Framework是用于开发Java Web应用程序和RESTful Web Servic…

springboot jwt token前后端分离_「转」七个开源的 Spring Boot 前后端分离项目,建议收藏加转载...

其实前后端分离本身并不难&#xff0c;后段提供接口&#xff0c;前端做数据展示&#xff0c;关键是这种思想。很多人做惯了前后端不分的开发&#xff0c;在做前后端分离的时候&#xff0c;很容易带进来一些前后端不分时候的开发思路&#xff0c;结果做出来的产品不伦不类&#…

联想办公计算机,办公娱乐两不误!联想这些笔记本电脑不容错过

【PConline 海选导购】随着技术的进步&#xff0c;如今的笔记本电脑性能越来越强&#xff0c;尤其是笔记本电脑携带更加方便&#xff0c;可以让你摆脱使用场景的限制&#xff0c;能随时随地畅玩游戏或者进行日常办公&#xff0c;有着台式机无可比拟的优势&#xff0c;因此&…

ftp主要完成与远程计算机的连接,2015计算机三级《网络技术》复习重点:远程登录服务和FTP服务...

2015计算机三级《网络技术》复习重点&#xff1a;远程登录服务和FTP服务一、远程登录服务(TCP连接)(TCP的23端口服务)1、远程登录协议用户使用Telnet命令&#xff0c;使自己的计算机成为远程计算机的一台仿真终端。远程登录允许任意类型的计算机之间进行通信&#xff0c;具体实…

度量空间的应用_使用Dropwizard度量标准监视和测量无功应用

度量空间的应用在上一篇文章中&#xff0c;我们创建了一个简单的索引代码&#xff0c;该代码可以对ElasticSearch进行数千个并发请求。 监视系统性能的唯一方法是老式的日志记录语句&#xff1a; .window(Duration.ofSeconds(1)) .flatMap(Flux::count) .subscribe(winSize -&…

rust的权限柜怎么做_潍坊装修知识~二胎家庭不做上下铺,把两张床靠墙放,中间做收纳柜,你感觉怎么样?...

如今装修最受关注也最让人头疼的就是儿童房装修了&#xff0c;身边二胎家庭、双胞胎家庭也是越来越多&#xff0c;如果户型小&#xff0c;再面对那只有几十平的小户型&#xff0c;2个孩子无法避免的要挤一间卧室&#xff01;所以对于儿童床的摆放和收纳该如何合理安排呢&#x…

java方法示例注释 @_Java 8中的功能接口是什么? @功能注释和示例

java方法示例注释 函数接口是Java 8最重要的概念之一&#xff0c;实际上为lambda表达式提供了动力&#xff0c;但是许多开发人员没有首先了解函数接口在Java 8中的作用就花了很多精力来理解它&#xff0c;并花时间学习lambda表达式和Stream API。除非您知道什么是功能接口以及l…

sql 除法_七天学会SQL-04SQL复杂查询

一、视图&#xff08;以下SQL操作都在Navicat客户端下操作&#xff09;1、什么是视图&#xff1f;1.是什么&#xff1f; 视图存放sql查询语句&#xff0c;使用视图时&#xff0c;会运行视图里的sql查询语句创造出一张临时表&#xff1b;如需频繁使用一段sql查询语句时可将该查询…

r中rep_Spring中@ Component,@ Service,@ Controller和@Repository之间的区别

r中rep在了解Spring框架中Repository Component &#xff0c; Service Controller &#xff0c; Repository Controller和Repository批注之间的区别之前&#xff0c;了解Component批注在Spring中的作用很重要。 在Spring的初始发行期间&#xff0c;所有bean都用于在XML文件中声…

adf4351使用_使用ADF绑定创建视图对象行CreateInsert操作

adf4351使用在这篇简短的文章中&#xff0c;我将重点介绍与在任务流中创建新记录的一种非常常见的方法有关的一个小陷阱。 让我们考虑一个简单的任务流程示例&#xff0c;该任务流程创建一个新的VO行&#xff0c;如果用户单击“确定”按钮&#xff0c;则在页面片段上显示该行并…

css鼠标移入线条延中心伸长,css动画效果:鼠标移上去底部线条从中间往两边延伸 - 子成君-分享出去,快乐加倍!-旧版已停更...

本站已不再更新,最新资源请前往zcjun.com获取!css&#xff1a;.top-nav a:after {content: ;position: absolute;z-index: 2;bottom: 0;left: 50%;display: block;width: 165px;height: 1px;transform: translate(-50%);}.top-nav a:hover:after {height: 2px;animation: ad_w…

css 深度选择器 ,CSS的coped私有作用域和深度选择器

大家都知道当 编译前&#xff1a;.example {color: red;}编译后&#xff1a;.example[data-v-f3f3eg9] {color: red;}看完你肯定就会明白了&#xff0c;其实是在你写的组件的样式&#xff0c;添加了一个属性而已&#xff0c;这样就实现了所谓的私有作用域。但是也会有弊端&…

营销自动化权威指南_免费电子书:自动化根本原因分析的完整指南

营销自动化权威指南自动化根本原因分析入门指南。 我们在OverOps过夜&#xff0c;梦想着拥有一个自动化的世界。 看起来似乎有些怪异&#xff0c;但是您能想象您和您的团队会比那些不眠之夜和无休止的日子在日志文件中筛选以找出问题出在哪里的快乐多了吗&#xff1f; 这些乏…

光立方原理讲解_90%人不理解什么是防眩光射灯 防昡晕 防炫光,。怎么选项led防眩灯...

关于LED射灯“防眩光(防炫光)”实在想和各位朋友讲解一下防眩光原理 &#xff0c;因为我们碰到90%以上装修朋友&#xff0c;总是把眩光理解为简单的不刺眼的光。我可以负责的告诉大家 &#xff0c;市面上没有不刺眼的射灯&#xff0c;不管是LED芯片直接射出来的光&#xff0c;还…

打印机设置虚拟服务器,虚拟机打印机服务器设置

虚拟机打印机服务器设置 内容精选换一换迁移前&#xff0c;您需要设置目的端服务器。该目的端用来接收源端的数据&#xff0c;同时您也可以使用该目的端进行迁移测试和启动目的端。只有“迁移阶段”为“已就绪”时才可设置目的端。或单击“操作”列的“更多 > 设置目的端”&…

datastore_使用Spring Session和JDBC DataStore进行会话管理

datastore在Web应用程序中&#xff0c;用户会话管理对于管理用户状态至关重要。 在本文中&#xff0c;我们将学习在集群环境中管理用户会话所采用的方法&#xff0c;以及如何使用Spring Session以更简单和可扩展的方式实现该方法。 通常在生产环境中&#xff0c;我们将有多个服…

做一个公众号大概要多少钱_公众号流量主一个月可以赚多少钱?

我是小郁儿&#xff0c;点击上方“关注”&#xff0c;每天为你分享自媒体运营与个人精进干货。细心的读者会发现&#xff0c;阅读我文章的时候&#xff0c;最下面不再出现广告卡片了&#xff0c;因为我前几天已经把流量主功能关掉。起初是因为我在看自己发的视频时&#xff0c;…

从Speedment 3.0.17或更高版本的事务轻松返回值

交易次数 在我以前的文章中&#xff0c;我写了关于如何使用Speedment轻松使用事务的方法&#xff0c;其中我们原子地更新了两个银行帐户。 众所周知&#xff0c;事务是一种将多个数据库操作组合到一个原子执行的单个操作中的方法。 但是事务不仅与更新数据库有关&#xff0c;而…

分布式锁的三种实现方式_分布式锁的多种实现方式

目前几乎很多大型网站及应用都是分布式部署的&#xff0c;分布式场景中的数据一致性问题一直是一个比较重要的话题。分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;和分区…