很少使用“ ControlFlowException”

控制流是命令式编程的“遗留物”,它已泄漏到其他各种编程范例中,包括Java的面向对象范例 。 除了有用的和无处不在的分支和循环结构外,还包括原语(例如GOTO)和非局部变量(例如异常)。 让我们仔细看看这些有争议的控制流技术。

goto是Java语言中的保留字 。 goto也是JVM字节码中的有效指令。 但是,在Java中,执行goto操作并不容易。 可以从以下堆栈溢出问题中获取一个示例 :

向前跳

label: {// do stuffif (check) break label;// do more stuff
}

在字节码中:

2  iload_1 [check]3  ifeq 6          // Jumping forward6  ..

向后跳

label: do {// do stuffif (check) continue label;// do more stuffbreak label;
} while(true);

在字节码中:

2  iload_1 [check]3  ifeq 96  goto 2          // Jumping backward9  ..

当然,这些技巧仅在非常罕见的情况下才有用,即使那样,您可能仍要重新考虑。 因为我们都知道在代码中使用goto会发生什么:

取自xkcd的图形: http : //xkcd.com/292/

打破控制流与例外

异常是在发生错误或故障时突破控制流结构的好工具。 但是也可以使用异常来定期向下跳转(没有错误或失败):

try {// Do stuffif (check) throw new Exception();// Do more stuff
}
catch (Exception notReallyAnException) {}

这就像前面提到的涉及标签的技巧一样让人感到困惑。

合法使用异常控制流:

但是,在其他一些非常罕见的情况下,异常是摆脱复杂的嵌套控制流(没有错误或失败)的好工具。 当您使用SAXParser解析XML文档时,可能就是这种情况。 也许,您的逻辑将要测试至少三个<check/>元素的出现,在这种情况下,您可能希望跳过对文档其余部分的分析。 这是实现上述内容的方法:

创建一个ControlFlowException

package com.example;public class ControlFlowException 
extends SAXException {}

请注意,通常,您可能更喜欢使用RuntimeException ,但是SAX合同要求处理程序实现抛出SAXException

在SAX处理程序中使用该ControlFlowException

package com.example;import java.io.File;import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;public class Parse {public static void main(String[] args) throws Exception {SAXParser parser = SAXParserFactory.newInstance().newSAXParser();try {parser.parse(new File("test.xml"),new Handler());System.out.println("Less than 3 <check/> elements found.");} catch (ControlFlowException e) {System.out.println("3 or more <check/> elements found.");}}private static class Handler extends DefaultHandler {int count;@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) {if ("check".equals(qName) && ++count >= 3)throw new ControlFlowException();}}
}

何时将异常用于控制流:

对于SAX,上述实践似乎是合理的,因为SAX合同期望发生此类异常,即使在这种情况下,它们不是异常而是常规控制流。 以下是在实际示例中何时使用上述做法的一些提示:

  • 您想突破复杂的算法(而不是简单的块)。
  • 您可以实现“处理程序”以将行为引入复杂的算法中。
  • 这些“处理程序”明确允许在合同中抛出异常。
  • 您的用例不会真正重构复杂算法。

真实示例:使用jOOQ进行批处理查询

在jOOQ中 ,可以“批量存储”记录的集合。 jOOQ不会为每个记录运行单个SQL语句,而是会收集所有SQL语句并执行JDBC批处理操作以一次存储所有这些SQL语句。

由于每条记录都以面向对象的方式封装了给定store()调用的生成的SQL渲染和执行,因此以可重用的方式提取SQL渲染算法而不破坏(或暴露)太多东西将非常棘手。 相反,jOOQ的批处理操作实现了以下简单的伪算法:

// Pseudo-code attaching a "handler" that will
// prevent query execution and throw exceptions
// instead:
context.attachQueryCollector();// Collect the SQL for every store operation
for (int i = 0; i < records.length; i++) {try {records[i].store();}// The attached handler will result in this// exception being thrown rather than actually// storing records to the databasecatch (QueryCollectorException e) {// The exception is thrown after the rendered// SQL statement is availablequeries.add(e.query());                }
}

一个真实的例子:异常变化的行为

jOOQ的另一个示例显示了此技术如何可用于引入仅在极少数情况下适用的异常行为。 如问题#1520中所述 ,某些数据库在每个语句可能的绑定值数量方面存在限制。 这些是:

  • SQLite:999
  • 英格莱斯10.1.0:1024
  • Sybase ASE 15.5:2000
  • SQL Server 2008年:2100

为了规避此限制,一旦达到最大值,jOOQ必须内联所有绑定值。 由于jOOQ的查询模型通过应用复合模式大量封装了SQL呈现和变量绑定行为,因此在遍历查询模型树之前无法知道绑定值的数量。 有关jOOQ的查询模型架构的更多详细信息,请考虑以下先前的博客文章: http ://blog.jooq.org/2012/04/10/the-visitor-pattern-re-visited

因此,解决方案是呈现SQL语句并计算将要呈现的绑定值。 规范的实现将是以下伪代码:

String sql;query.renderWith(countRenderer);
if (countRenderer.bindValueCount() > maxBindValues) {sql = query.renderWithInlinedBindValues();
}
else {sql = query.render();
}

可以看出,规范的实现将需要两次渲染SQL语句。 第一个渲染仅用于计算绑定值的数量,而第二个渲染将生成真实的SQL语句。 这里的问题是,一旦异常事件(绑定值太多)发生,异常行为就应该被放置。 更好的解决方案是引入一个“处理程序”,在常规的“渲染尝试”中对绑定值进行计数,并为绑定值数量超过最大值的少数例外“尝试”抛出ControlFlowException

// Pseudo-code attaching a "handler" that will
// abort query rendering once the maximum number
// of bind values was exceeded:
context.attachBindValueCounter();
String sql;
try {// In most cases, this will succeed:sql = query.render();
}
catch (ReRenderWithInlinedVariables e) {sql = query.renderWithInlinedBindValues();
}

第二种解决方案更好,因为:

  • 我们仅在例外情况下重新呈现查询。
  • 我们还没有完成呈现查询以计算实际计数,而是提早中止以重新呈现。 即我们不在乎是否有2000、5000或100000绑定值。

结论

与所有特殊技术一样,请记住在正确的时机使用它们。 如有疑问,请三思。

参考:在JAVA,SQL和JOOQ博客上, JCG合作伙伴 Lukas Eder 很少使用“ ControlFlowException” 。

翻译自: https://www.javacodegeeks.com/2013/05/rare-uses-of-a-controlflowexception.html

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

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

相关文章

使用Amazon Web Services(EC2)

正如我上周参加技术动手AWS培训之前所发布的。 这些天的课程当然是我以前使用过的标准EC2和S3服务。 除此之外&#xff0c;我们还使用了RDS &#xff0c; Elastic Load Balancing &#xff0c; SNS和VPC &#xff0c; Elastic Beanstalk并讨论了许多术语和业务案例。 在本文中&…

盒子模型阴影设置,爱奇艺阴影配置

box-shadow的配置阴影 ul li:hover{ border-color: #dfdfdf; border-radius: 10px; -moz-box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1), 0 0 10px 0 rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1), 0 0 10px 0 rgba(0, 0, 0, 0.2); box-shadow: 0 5px 5…

第四周PSP

1.本周PSP 2.本周进度条 3.本周累计进度图 代码积累折线图 博文字数积累折线图 4.本周PSP饼状图 转载于:https://www.cnblogs.com/yuanyue-nenu/p/7648565.html

适用于JDeveloper 11gR2的Glassfish插件

众所周知&#xff0c; ADF Essentials是使用Java构建Web应用程序的绝佳框架&#xff0c;它可以自由开发和部署。 您可以在Glassfish&#xff08;3.1&#xff09;服务器上部署ADF Essentials应用程序。 但是&#xff0c;JDeveloper并不带有嵌入式Glassfish服务器&#xff0c;而是…

java 李刚 pdf_Java数据库技术详解(李刚) PDF_源雷技术空间

资源名称&#xff1a;Java数据库技术详解(李刚) PDF第一篇 数据库基础篇第1章 Java和数据库 21.1 Java概述 21.1.1 跨平台性 21.1.2 面向对象 21.1.3 安全性 31.1.4 简单性 31.1.5 健壮性和自动内存管理 31.2 Java的开发和运行环境 31.2.1 JDK的安装 31.2.2 配置JDK的环境变量 …

Java EE CDI处理程序方法示例

这是CDI Disposer方法的教程。 在CDI中&#xff0c;由于Producer方法生成的对象随后可以注入到应用程序中&#xff0c;因此使用Disposer方法&#xff0c;以便在其工作完成时将其删除。 Disposer方法始终与Producer方法匹配。 Disposer方法的使用示例是应用程序使用与数据库的连…

转 如何更改linux文件的拥有者及用户组(chown和chgrp)

本文整理自&#xff1a; http://blog.163.com/yanenshun126/blog/static/128388169201203011157308/http://ydlmlh.iteye.com/blog/1435157一、基本知识在Linux中&#xff0c;创建一个文件时&#xff0c;该文件的拥有者都是创建该文件的用户。该文件用户可以修改该文件的拥有者…

上下div高度动态自适应--另类处理方案

这段时间在工作中遇到一个看似较为棘手的问题。问题描述&#xff1a;查询报表页面分为上下两部分&#xff0c;上部分为条件输入区域&#xff0c;下部分为报表展示区域。客户要求做到默认满屏&#xff08;但要动态适应不同的窗体大小&#xff0c;也就是浏览器窗体用户会手动改变…

201571030316/201571030314 《小学四则运算练习软件需求说明》结对项目报告

小伙伴儿的博客地址链接&#xff1a;http://www.cnblogs.com/mjuan/p/8877738.html 我的学号&#xff1a;201571030316 小伴儿的学号&#xff1a;201571030314 一、调研过程&#xff1a; 1. 调查问卷&#xff1a;https://www.wjx.cn/jq/22680271.aspx利用问卷…

23种设计模式之一(单例模式)

单例模式&#xff1a;&#xff08;确保一个类最多只有一个实例&#xff0c;并提供一个全局访问点&#xff09; 存在的意义&#xff1a; 有些对象我们只需要一个&#xff0c;如&#xff1a;线程池、缓存、硬件设备等&#xff1b;如果使用多个实例就会造成冲突、不一致等&#xf…

mysql监控

1、查看mysql所有线程&#xff1a;show full processlist;SHOW PROCESSLIST显示哪些线程正在运行。如果您有SUPER权限&#xff0c;即root权限之类&#xff0c;您可以看到所有线程。否则&#xff0c;您只能看到您自己的线程&#xff08;也就是&#xff0c;与您正在使用的MySQL账…

vSphere ESXi主机配置iSCSI存储

vSphere ESXi主机配置iSCSI存储 vSphere ESXi主机一般连接的存储类型有光纤存储、iSCSI存储两类。本次案例为iSCSI存储连接ESXi主机的配置。 案例环境&#xff1a;ESXi主机通过以太网络来连接iSCSID存储&#xff0c;并获取到存储空间&#xff0c;拓扑如下&#xff1a; 首先完成…

linux上验证cudnn是否安装成功_deepin15.7中安装tensorflow+cuda9.0+cudnn7的步骤

这次deepin15.7大更新&#xff0c;特别是深度学习环境搭建屡屡失败&#xff0c;很是恼火。本次按照下面的步骤做成功了&#xff0c;以下是deepin15.7下安装tensorflowcuda9.0cudnn7的全部流程。硬件1.神舟战神z7-kp7s1&#xff0c;双显卡双硬盘2.独显是gtx1060 6G系统安装1.下载…

【ichart】简单的统计图表ichart.js的使用

1、首先下载&#xff0c;点击下载 2、只需要这一个js&#xff0c;粘贴赋值到自己项目中即可。 3、引入js <script type"text/javascript" src"../js/ichart.1.2.min.js"></script> <script type"text/javascript" src"..…

ActiveMQ——activemq的使用java代码实例(精选)

ActiveMQ 在java中的使用&#xff0c;通过单例模式、工厂实现 Jms规范里的两种message传输方式Topic和Queue&#xff0c;两者的对比如下表()&#xff1a; TopicQueue概要Publish Subscribe messaging 发布订阅消息Point-to-Point 点对点有无状态topic数据默认不落地&#xff…

Eclipse+GitHub 提交代码错误 -“rejected - non-fast-forward”

Eclipse Push出现rejected - non-fast-forward错误 在 Push到服务器时有时会出现 rejected - non-fast-forward 错误&#xff0c;这是由于远端发生改变&#xff0c;此时再提交之前你需要将远端的改变合并到本地上错误原因&#xff1a;文件冲突&#xff0c;本地的代码和远程Repo…

两天学会css基础(一)

什么是css&#xff1f;css的作用是什么&#xff1f; CSS 指层叠样式表 (Cascading Style Sheets)主要作用就是给HTML结构添加样式&#xff0c;搭建页面结构&#xff0c;比如设置元素的宽高大小&#xff0c;颜色&#xff0c;位置等等。 学习css之前先了解一下css代码在HTML中的…

LVM 逻辑卷 (logica volume manager)

逻辑卷轴管理员 (Logical Volume Manager) 想像一个情况&#xff0c;你在当初规划主机的时候将 /home 只给他 50G &#xff0c;等到使用者众多之后导致这个 filesystem 不够大&#xff0c; 此时你能怎么作&#xff1f; 多数的朋友都是这样&#xff1a;再加一颗新硬盘&#xff0…

sql查询语句for xml path语法

【原地址】 for xml path作用&#xff1a;将多行的查询结果&#xff0c;根据某一些条件合并到一行。 例&#xff1a;现有一张表 执行下面语句 select Department,(SELECT Employee, FROM People b WHERE b.Departmenta.Department For XML Path()) Student from People as a g…

Android Studio打包以及Gradle配置构建

本文转载 郭霖公众号 https://mp.weixin.qq.com/s?__bizMzA5MzI3NjE2MA&mid2650241610&idx1&snb8af73f6c288b6617d9fe0ab3618118d&pass_ticketQK4j37kpmGNlsYcECWMb64HxKHEVJG5mSJubQEQguKI%3D 生成签名文件手动打包 首先生成签名文件&#xff0c;点击 Build…