重复码

介绍

在我们的Java应用程序中复制/粘贴代码通常不好,但是有时这是不可避免的。 例如,项目License3j在Feature类中为其支持的每种XXX类型提供了一个isXXX方法。 在这种情况下,我们要做的就是写

 public boolean isBinary() { return type == Type.BINARY; } public boolean isString() { return type == Type.STRING; } public boolean isByte() { return type == Type.BYTE; } public boolean isShort() { return type == Type.SHORT; }  and so on 

应用程序支持的每种功能类型。 那里有一些类型:Binary,String,Byte,Short,Int,Long,Float,Double,BigInteger,BigDecimal,Date,UUID。 键入所有非常相似的方法不仅是无聊的任务,而且容易出错。 很少有人擅长执行此类重复性任务。 为了避免这种情况,我们可以使用Java :: Geci框架,作为最简单的解决方案,我们可以使用生成器Iterate。

POM依赖

要使用生成器,我们必须添加依赖项

 < dependency > < groupId >com.javax0.geci</ groupId > < artifactId >javageci-core</ artifactId > < scope >test</ scope > < version >1.4.0</ version >  </ dependency > 

该库仅在测试运行时执行,因此使用它并不意味着任何额外的依赖关系。 谁想要使用许可证3j库都不需要使用Java :: Geci。 这只是test范围中使用的开发工具。

单元测试运行

依赖关系不会自行运行。 毕竟依赖不是程序。 它是打包到JAR中的一堆类文件,可在类路径上使用。 我们必须执行生成器,并且必须通过创建单元测试的框架来完成:

 @Test @DisplayName ( "run Iterate on the sources" ) void runIterate() throws IOException { Geci geci = new Geci(); Assertions.assertFalse( geci.register(Iterate.builder() .define(ctx -> ctx.segment().param( "TYPE" , ctx.segment().getParam( "Type" ).orElse( "" ).toUpperCase())) .build()) .generate() , geci.failed() ); } 

它创建一个Geci对象,使用生成器实例Geci ,然后在配置的框架Geci对象上调用generate() 。 就目前而言, define()调用似乎有点神秘。 稍后我们将阐明这一点。

源代码准备

执行构建之前的最后一步是定义模板以及要插入模板的值。 无需编写所有方法,而是编写模板和编辑器折叠段:

 /* TEMPLATE LOOP Type=Binary|String|Byte|Short|Int|Long|Float|Double|BigInteger|BigDecimal|Date|UUID public boolean is{{Type}}() { return type == Type.{{TYPE}}; } */ //<editor-fold id="iterate"> //</editor-fold> 

当我们通过框架执行生成器时,它将为占位符Type每个值评估模板,并将每个{{Type}}替换为实际值。 生成的代码将插入id “ iterate”的编辑器折叠段中。

查看模板,您会发现有一个占位符{{TYPE}} ,未在列表中定义。 这是统一测试define()进入图片的地方。 它定义一个使用上下文的使用者,并使用该上下文读取Type的实际值,创建该值的大写版本并将其分配给名为TYPE的段参数。

通常就是这样。 使用生成器还有其他功能,例如每次迭代定义多个值分配给不同的占位符,转义或跳过行等。 关于这些内容的摘录是您可以阅读文档的摘录,您可以阅读最新且完整的内容https://github.com/verhas/javageci/blob/master/ITERATE.adoc

文档摘录

在要使用生成器的Java源文件中,必须使用注释@Geci("iterate")来注释该类。
您也可以改用@Iterate批注,该批注在
javageci-core-annotations模块。 这将指示Geci框架您要在给定类中使用iterate生成器。

TEMPLATE

模板在/\*TEMPLATETEMPLATE行之后开始。
/*和单词之间前后可以有空格
TEMPLATE但线上不应有其他任何东西。 当生成器看到这样的行时,它将开始收集以下行作为模板的内容。

模板的末尾由一行上带有*/信号线表示,没有其他内容(空格除外)。

模板的内容可以包含{{}}之间的参数
字符,与胡子模板程序使用的字符类似。
(生成器不使用胡须,模板处理更为简单。)

LOOP

在收集模板的行时,某些行被识别为模板的参数定义。 这些行不会进入模板的主干。 (这些行上的命令名称始终为大写。)

如您在简介中所见

 LOOP type =int|long|short 

不是模板文本的一部分。 它通过类型指示发生器迭代并设置参数{{type}}在文本到int第一, long第二和short的最后。 这样,您可以遍历单个参数的多个值。

更复杂的模板可能需要多个参数。 在这种情况下,您可以将它们在LOOP行中列出为

 LOOP type ,var=int,aInt|long,aLong|short,aShort 

这将告诉生成器将参数设置{{type}}相同的方式,前三个迭代,但同时也设置了参数{{var}}aInt在第一循环中,以aLong在第二循环中和最后一个循环中的aShort

如果值列表太长,则可以将列表分成多条LOOP行。 但是,在这种情况下,必须在第二行,第三行等等在LOOP行中重复这些变量。
它们的顺序可能有所不同,但是如果某些LOOP行中存在未定义的变量,则将解析引用该变量的占位符并将其保留为{{placeholder}}形式。

上面的例子也可以写成

 LOOP type ,var=int,aInt LOOP var, type =aLong,long LOOP type ,var=short,aShort 

并得出与上述LOOP相同的值:

 LOOP type ,var=int,aInt|long,aLong|short,aShort 

默认

从文件的开头到结尾处理模板,并按此顺序准备生成的代码。
生成的代码的内容将直接插入模板editor-foldeditor-fold部分。 虽然这样的id
editor-fold段并不是很有趣,您必须为每个段指定一个唯一的id 。 这是Java :: Geci框架的限制。

进阶使用

EDITOR-FOLD-ID

您可能会遇到多个模板,这些模板遍历不同的值,并且您希望结果进入相同的editor-fold
分割。 可以使用EDITOR_FOLD_ID

在下面的例子中

 package javax0.geci.iterate.sutclasses;  public class IterateOverMultipleValues { /* TEMPLATE {{ type }} get_{{ type }}Value(){ {{ type }} {{variable}} = 0; return {{variable}}; } LOOP type ,variable=int,i|long,l|short,s EDITOR-FOLD-ID getters */ // // nothing gets here // // int get_intValue(){ int i = 0; return i; } long get_longValue(){ long l = 0; return l; } short get_shortValue(){ short s = 0; return s; } //  } 

生成的代码进入具有id名称的editor-fold
getters即使这不是遵循模板定义的getters

使用此功能可以将生成的代码从多个迭代模板发送到单个段中。 通常,将模板和段保持在一起是一个好习惯。

ESCAPESKIP

模板的结尾由*/ 。 这实质上是评论的结尾。 如果要在模板中包含注释(如JavaDoc),会发生什么情况。 您可以在注释行的末尾添加*/字符,但其中仍包含一些字符。 该解决方案不是很好,它实际上是一种解决方法。

要有一条完全是注释结尾的行,或者是模板处理可以解释的任何行,例如LOOP行,您应该在前一行中包含除ESCAPE任何行。 这将告诉模板处理将下一行包括在模板文本中,并在此后的行继续进行正常处理。

同样,您可以使用SKIP行来完全忽略下一行。
使用这两个命令,您可以将任何内容包括到模板中。

一个示例显示如何将JavaDoc注释包括到模板中:

 package javax0.geci.iterate.sutclasses;  public class SkippedLines { /* TEMPLATE /** * A simple zero getter serving as a test example * @ return zero in the type {{ type }} ESCAPE */ // SKIP /* {{ type }} get_{{ type }}Value(){ {{ type }} {{variable}} = 0; return {{variable}}; } LOOP type ,variable=int,i|long,l|short,s EDITOR-FOLD-ID getters */ // /** * A simple zero getter serving as a test example * @ return zero in the type int */ int get_intValue(){ int i = 0; return i; } /** * A simple zero getter serving as a test example * @ return zero in the type long */ long get_longValue(){ long l = 0; return l; } /** * A simple zero getter serving as a test example * @ return zero in the type short */ short get_shortValue(){ short s = 0; return s; } //  } 

模板以注释开头,并且注释实际上可以包含任何其他开头的注释。 Java注释不嵌套。 模板的末尾是包含*/字符串的行。 我们希望该行成为模板的一部分,因此我们在该行之前
ESCAPE因此它不会被解释为模板的末尾。 另一方面,对于Java,这将结束注释。 要继续模板,我们必须“返回”注释模式,因为我们不希望Java编译器将模板作为代码来处理。 (最后但并非最不重要的一点是,因为使用占位符的模板可能不是语法上正确的Java代码片段。)我们需要一个新的/*行,我们不想将其插入模板。
因此,此行之前包含// SKIP的行。 (跳过行在命令前可以具有// 。)

您可以在生成的代码中看到的结果。 所有方法都具有正确的JavaDoc文档。

SEP1SEP2

遍历值已与占位符的名字分开,并且| 值列表。 例如,上面的示例包含

 LOOP type ,variable=int,i|long,l|short,s 

两个占位符名称typevariable ,每个占位符三个值。
占位符不需要包含特殊字符,如果它们是标准标识符,则最好。 但是,这些值可能包含逗号或竖线。 在这种情况下,你可以重新定义字符串(不仅是单个字符),模板LOOP命令可以改用单一字符串,|

例如线

 SEP1 / 

表示名称和值应以/分隔,而不是一个和

 SEP2 & 

的值的列表应当由一个字符分隔&
串。 SEP1SEP2仅在它们之前
LOOP命令,它们仅对所使用的模板有效。遵循上述命令, LOOP示例将如下所示:

 LOOP type /variable =int /i &long /l &short /s 

这样,没有什么可以阻止我们添加另一个值列表

 LOOP type /variable =int /i &long /l &short /s &byte,int /z 

最终将导致示例模板出现语法错误,但演示了重新定义名称和值列表分隔符的要点。

组态

生成器由Geci框架支持的配置工具实现,并且所有参数都是可配置的。 您可以在类的注释中或在编辑器折叠参数中,重新定义与模板的开始,结束,跳过等行相匹配的正则表达式,在创建生成器对象的单元测试中。

带走

迭代生成器是一种非常易于使用的生成器,用于创建重复的代码。 这也是主要的危险:您应该足够强大才能找到更好的解决方案,并仅在最佳解决方案时才使用它。

翻译自: https://www.javacodegeeks.com/2019/11/repeated-code.html

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

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

相关文章

sap tcode 功能对照表_Python for Ev3练习amp;Minstorms对照表02

大家好。我是欧文今天给大家分享python for Ev3的练习代码以及python中对应的Ev3Minstorms软件模块对照表。这个练习题都相对基础。主要是用来练习用的。给大家分享的代码也是比较简单的&#xff0c;不过实现方法都是不唯一的。主要的目的是练习和学习。练习代码如下&#xff1…

大楼通信综合布线系统_某办公大楼综合布线系统设计实例,小白可以借鉴一下,大神请绕路...

xxx办公大楼综合布线系统是一个包括内部数据语音通信、外线电话线路接入管理系统、办公用强电电气配电系统、电缆电视系统等内部的复合布线系统&#xff0c;在会议室还有一个小型的供音响系统设备使用的专用布线系统。各子系统的基本情况及主功能如下&#xff1a;强电配电系统&…

java8日期_Java8日期与时间

我们知道Java8一个比较大的改动就是引入了新的表示日期和时间的API&#xff0c;还是很有必要抽点时间了解一下基本的用法。Java8之前的问题在讨论Java8的API之前&#xff0c;我们先看看原来API的问题。我们知道Java8之前只有java.util.Date和java.util.Calendar来表示和处理时间…

javaone_为JavaOne 2014做好准备!

javaone保持那个想法&#xff01; 是的&#xff0c;我希望我能在Java One 2014上做演讲-但我现在只值得在梦里做到这一点&#xff01; 但是&#xff0c;没有什么阻止我遵循Java One并跟踪有关我最喜欢的主题的会话/对话。 我希望Oracle能够像我们2013年版那样&#xff0c;像我…

代码逻辑分析_双11模块79.34%的前端代码是怎样智能生成的?

作者&#xff5c;妙净、波本最近几年&#xff0c;AI 渗透到开发领域的方方面面。在前端领域&#xff0c;设计稿生成代码(简称 D2C)就是一个例子。其目标在于通过 AI 助力前端提效升级&#xff0c;杜绝简单重复性的工作内容。今年“双十一”&#xff0c;阿里的 D2C 覆盖了天猫淘…

datax导入MySQL报错_导入MySQL方法对比

使用datax导入1、使用自增id记录数耗时(秒)TPS42488823471224433404813403882722、不使用自增id&#xff0c;使用雪花算法生成id后导入记录数耗时(秒)TPS424888268062483340481365555096使用MySQL命令load导入1、csv带雪花id> select * from l_wish_log_snow_copy into outf…

项目织机

为什么为什么&#xff1f; Java 8流背后的驱动程序之一是并发编程。 在流管道中&#xff0c;指定要完成的工作&#xff0c;然后任务将自动分发到可用处理器上&#xff1a; var result myData.parallelStream().map(someBusyOperation).reduce(someAssociativeBinOp).orElse(…

java mybatis 教程_(整理)MyBatis入门教程(一)

本文转载&#xff1a;本人文笔不行&#xff0c;根据上面博客内容引导&#xff0c;自己整理了一些东西首先给大家推荐几个网页&#xff1a;MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code&#xff0c;并且改名为MyBa…

2020版北大中文核心期刊目录_收藏备用最新版:《中文核心期刊要目总览》北大中文核心期刊目录...

《中文核心期刊要目总览》是学术界对某类期刊的定义&#xff0c;一种期刊等级的划分。它的对象是&#xff0c;中文学术期刊&#xff0c;是根据期刊影响因子等诸多因素所划分的期刊。中文核心期刊是北京大学图书馆联合众多学术界权威专家鉴定&#xff0c;目前受到了学术界的广泛…

java中多个输入框搜索_如何在一个搜索框中输入多个字段的值进行查询?

搜索export default {data() {return {input: ,//用来接受input框的值name:,// 用来存储foreach的对应的值id:,// 用来存储foreach的对应的值dq:// 用来存储foreach的对应的值}},methods:{submit(){console.log(this.input);// 打印let str this.input;// 声明变量接受input的…

fedora如何隐藏顶部状态栏_藏在 iOS 13 里的 9 个隐藏小技巧

正文共&#xff1a;1797字 10图1.从控制中心直接选择无线网络和蓝牙配件苹果首次在 iOS 7 中加入了控制中心&#xff0c;允许用户进行一些快速操作&#xff0c;例如打开/关闭飞行模式、打开/关闭蜂窝网络、打开/关闭 Wi-Fi 等。但很多控制都只停留在一级菜单&#xff0c;你只能…

摇篮配置

在这篇文章中&#xff0c;我们将介绍有关Gradle配置的综合文章。 1.技术 Gradle是用于自动任务管理的开源构建工具。 它基于Apache Ant&#xff0c;Apache Maven的概念。 Gradle是使用Groovy语言开发的。 Gradle是使用基于Groovy的领域特定语言&#xff08;DSL&#xff09;开发…

java的封装性的优点_18、Java的三大特性之封装

Java的三大特性java是一个面向对象的语言&#xff0c;所以java也有面向对象语言的三大特性&#xff1a;继承&#xff0c;封装&#xff0c;多态&#xff0c;任何一个java项目&#xff0c;都会用到这三种特性&#xff0c;所以掌握好这三大特性非常的重要。封装我们为什么要使用封…

groovy 字符串截取最后一个_Java基础篇——字符串详解

字符串的声明字符串是内存中连续排列的0个或多个字符。不变字符串是指字符串一旦创建&#xff0c;其内容就不能改变&#xff0c;Java中使用String类来处理不变字符串&#xff0c;在对String类的实例进行查找、比较、拼接等操作时&#xff0c;既不能输入新字符&#xff0c;又不能…

eclipse插件开发_开发Eclipse插件

eclipse插件开发最近&#xff0c;我开始与一个团队合作开发Eclipse插件。 团队开发了一个很棒的插件&#xff0c;可以实现预期的目的。 因此&#xff0c;我检查了源并尝试构建它。 项目源包含所有必需的库&#xff0c;并且只能在Eclipse中构建。 在当今不断交付的世界中&#x…

java中链式调用_Java及Android中常用链式调用写法简单示例

本文实例讲述了Java及Android中常用链式调用写法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;最近发现&#xff0c;目前大火的许多开源框架中&#xff0c;大多都使用了一种"(方法).(方法).(方法)"的形式进行调用&#xff0c;最典型的就是RxJava。android…

Java记录

https://openjdk.java.net/jeps/359概述了新的Java功能&#xff0c;该功能可能会/将在某些将来的Java版本中实现。 JEP建议使用一种新型的“班级”&#xff1a;记录。 JEP中的示例内容如下&#xff1a; record Range( int lo, int hi) { public Range { if (lo > hi) /* ref…

C什么k什么_K线图基础知识丨什么是K线散兵坑形态?K线散兵坑形态的操作与案例详解...

本文总共999字&#xff0c;预计阅读需要3分钟今天我们给大家带来的是K线散兵坑形态&#xff0c;那么K线散兵坑形态应该怎么来操作呢&#xff1f;今天我们就结合相应的实战案例来为大家讲解一下吧。K线散兵坑形态的简介散兵坑是指在股价缓慢上涨过程中.成交量也逐渐放大&#xf…

support v4官方下载_掌心长兴客户端下载-掌心长兴ap下载v4.1.4 安卓官方版

掌心长兴app是一款为广大用户开发的新闻资讯软件。在这里用户可以清晰的了解今日热点新闻&#xff0c;最新新闻直播电台应有尽有&#xff01;让你全方面了解周边新鲜事&#xff01;还有各种常用功能的代办查询服务。有需要的用户&#xff0c;欢迎现在下载体验哦掌心长兴客户端介…

java简单计算机程序_JAVA程序编的简单计算器程序??

1 文件名&#xff1a;Calculate_GUI。javaimport javax。swing。*;import t。Container;import t。event。*;public class Calculate_GUI extends JFrame{private JPanel p1;private JButton keyButton[]new JButton[16],signButton,clearButton,deleteButton;private JTextFie…