Java方法中的参数太多,第1部分:自定义类型

我认为构造函数和方法中冗长的参数列表是Java开发中的另一个“ 危险信号 ”,就逻辑和功能而言,它们不一定是“错误的”,但通常暗示当前或将来出现错误的可能性很高。 在一小部分帖子中,我介绍了一些可用于减少方法或构造函数的参数数量,或至少使冗长的参数列表更易读且更不易出错的方法。 每种方法都有其自己的优点和缺点。 这篇文章开始该系列文章,重点是通过使用自定义类型提高长方法/构造函数参数列表的可读性和安全性。

冗长的方法和构造方法参数列表有几个缺点。 大量参数可能很乏味,并且难以调用代码使用。 较长的参数列表也可能导致调用中参数的无意切换。 在某些情况下,可能很难找到这些错误。 幸运的是,大多数方法不必处理冗长的参数列表的另一个缺点: JVM通过编译时错误 将参数的数量限制为一个方法 。

自定义类型的使用是一种不减少方法或构造函数的参数数量,但确实使这些较长的参数列表更易读且不太可能以错误的顺序提供的方法。 这些自定义类型可以实现为数据传输对象 (DTO), JavaBeans , 值对象 , 引用对象或任何其他自定义类型(在Java中,通常是类或枚举 )。

这是一个人为设计的方法示例,该方法接受多个参数,其中许多参数为String类型,许多参数为boolean类型。

/*** Instantiate a Person object.* * @param lastName* @param firstName* @param middleName* @param salutation* @param suffix* @param streetAddress* @param city* @param state* @param isFemale* @param isEmployed* @param isHomeOwner* @return */public Person createPerson(final String lastName,final String firstName,final String middleName,final String salutation,final String suffix,final String streetAddress,final String city,final String state,final boolean isFemale,final boolean isEmployed,final boolean isHomeOwner){// implementation goes here}

容易意外地切换它们并以错误的顺序传递它们。 尽管我通常希望减少参数,但是可以通过更改参数列表中的类型来进行一些改进。 接下来的代码清单显示了这些自定义类型的一些示例,这些示例可用于名称,地址,城市和布尔参数。

可以将三个name参数分别更改为Name的自定义类型,而不是String 。 接下来定义该Name类型。

名称.java

package dustin.examples;/*** Name representation.* * @author Dustin*/
public final class Name
{private final String name;public Name(final String newName){this.name = newName;}public String getName(){return this.name;}@Overridepublic String toString(){return this.name;}
}

称呼和后缀String类型也可以替换为自定义类型,如以下两个代码清单所示。

Salutation.java

package dustin.examples;/*** Salutations for individuals' names.* * @author Dustin*/
public enum Salutation
{DR,MADAM,MISS,MR,MRS,MS,SIR
}

后缀.java

package dustin.examples;/*** Suffix representation.* * @author Dustin*/
public enum Suffix
{III,IV,JR,SR
}

其他参数也可以用自定义类型替换。 接下来的代码清单显示了可以替换boolean以提高可读性的自定义枚举。

Gender.java

package dustin.examples;/*** Gender representation.* * @author Dustin*/
public enum Gender
{FEMALE,MALE
}

EmploymentStatus.java

package dustin.examples;/*** Representation of employment status.* * @author Dustin*/
public enum EmploymentStatus
{EMPLOYED,NOT_EMPLOYED
}

HomeOwnerStatus.java

package dustin.examples;/*** Representation of homeowner status.* * @author Dustin*/
public enum HomeownerStatus
{HOME_OWNER,RENTER
}

也可以使用定义的自定义类型来传递此人的地址信息,如以下代码清单所示。

StreetAddress.java

package dustin.examples;/*** Street Address representation.* * @author Dustin*/
public final class StreetAddress
{private final String address;public StreetAddress(final String newStreetAddress){this.address = newStreetAddress;}public String getAddress(){return this.address;}@Overridepublic String toString(){return this.address;}
}

City.java

package dustin.examples;/*** City representation.* * @author Dustin*/
public final class City
{private final String cityName;public City(final String newCityName){this.cityName = newCityName;}public String getCityName(){return this.cityName;}@Overridepublic String toString(){return this.cityName;}
}

State.java

package dustin.examples;/*** Simple representation of a state in the United States.* * @author Dustin*/
public enum State
{AK,AL,AR,AZ,CA,CO,CT,DE,FL,GA,HI,IA,ID,IL,IN,KS,KY,LA,MA,MD,ME,MI,MN,MO,MS,MT,NC,ND,NE,NH,NJ,NM,NV,NY,OH,OK,OR,PA,RI,SC,SD,TN,TX,UT,VA,VT,WA,WI,WV,WY
}

通过实现这些自定义类型,我们原始方法的签名变得更具可读性,并且不太可能意外地以错误的顺序提供参数。 这显示在下一个代码清单中。

public Person createPerson(final Name lastName,final Name firstName,final Name middleName,final Salutation salutation,final Suffix suffix,final StreetAddress address,final City city,final State state,final Gender gender,final EmploymentStatus employment,final HomeownerStatus homeowner){// implementation goes here}

在上面的代码清单中,编译器现在将通过不允许之前的大多数Stringboolean参数意外混合来帮助开发人员。 这三个名称仍然是一个潜在的问题,因为调用方可能会无序提供它们,但是如果我担心的话,我可以为FirstNameLastNameMiddleName编写特定的类型(类)。 相反,我更喜欢使用一个代表全名的新类,并将这三个名称全部用作其属性,但是该方法将成为以后处理Java方法的过多参数的主题。

优势与优势

在给定方法上处理多个参数时编写和使用自定义类型的优点包括代码维护者和使用API​​的开发人员的可读性。 具有多个相同类型的参数,不仅使开发人员可以轻松混合其顺序,还降低了IDE在使用代码完成功能时将适当建议与参数匹配的能力。 正确的命名可以对IDE有所帮助,但是对IDE而言,没有什么比使用这些自定义类型可以完成的静态编译时检查有用的了。 总的来说,我更愿意从运行时转移尽可能多的自动检查到编译时,并且让这些静态定义的自定义类型(而不是通用类型)来完成此任务。

此外,这些自定义类型的存在使将来更容易添加更多详细信息。 例如,将来我可以在不更改接口的情况下,将完整的状态名称或有关状态的其他详细信息添加到该枚举中。 我不可能用一个简单的String来表示状态。

成本与劣势

自定义类型方法最常被引用的缺点之一是额外的实例化和内存使用的开销。 例如, Name类需要实例化Name类本身及其封装的String 。 但是,我认为,这种争论通常是从过早优化的角度出发,而不是合理的衡量性能问题。 在某些情况下,额外的实例化过于昂贵,以至于无法证明增强的可读性和编译时检查,但是许多(也许大多数 )情况可以提供额外的实例化,而其可观察到的影响却可以忽略不计。 我很难相信使用自定义枚举而不是Stringboolean会在大多数情况下引入性能问题。

使用自定义类型而不是内置类型的另一个缺点是编写和测试这些自定义类型需要额外的精力。 但是,如本文中的示例所示,通常存在非常简单的类或枚举,并且不难编写或测试。 有了良好的IDE和良好的脚本语言(例如Groovy),它们特别容易自动编写和测试。

结论

我喜欢使用自定义类型来提高可读性,并将更多的参数类型检查负担转移到编译器上。 我没有更多地使用这种方法来提高具有非常长的参数列表的方法和构造函数的可读性的最大原因是,它本身并没有减少参数的数量。 它使长列表更易于阅读和使用,但调用方仍然必须编写笨拙的客户端代码才能调用该方法或构造函数。 因此,在改进接受一长串参数的方法时,我经常使用除自定义类型以外的技术。 这些其他技术将在以后的文章中探讨。

参考: Java方法中的参数过多,第1部分:来自JCG合作伙伴 Dustin Marx的“ 实际事件的启发”博客中的自定义类型 。

翻译自: https://www.javacodegeeks.com/2013/10/too-many-parameters-in-java-methods-part-1-custom-types.html

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

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

相关文章

mysql怎么制作柱状图_从数据库中取出最近三十天的数据并生成柱状图

在终端用cd 命令进入文件目录说明:此处例子我是拿项目中的一个例子讲解的。1、新建一个项目 :用终端输入:zf create project Airline 格式:zf create action project project-name 备注:这些格式可以在终端输入zf 查看…

关于ES6的Promise

JavaScript的异步处理 提到JavaScript的异步处理,也许很多人和我一样想到利用回调函数。 例如: firstAsync(function(data){//处理得到的 data 数据//....secondAsync(function(data2){//处理得到的 data2 数据//....thirdAsync(function(data3){//处…

为hexo博客添加基于gitment评论功能

关于gitment gitment其实就是利用你的代码仓库的Issues,来实现评论。每一篇文章对应该代码仓库中的 一个Issues,Issues中的评论对应你的博客每篇文章中的评论。如果你是用github的博客的话 用起来将会十分的方便。 注册github应用 首先需要在这注册一个OAuth Applic…

[转]我是如何走进黑客世界的?

*本文原创作者:MyselfExplorer;翻译编辑:楼兰,本文属FreeBuf原创奖励计划,未经许可禁止转载 我想给你一把打开这扇门的钥匙,而你要做的便是静静的聆听接下来的故事。挖掘 0day 一般需要掌握fuzzing&#xf…

使用Servlet 3.0,Redis / Jedis和CDI的简单CRUD –第1部分

在这篇文章中,我们将构建一个简单的用户界面。 数据将存储在Redis中。 为了与Redis交互,我们将使用Jedis库。 CDI用于Depedency Injection,而Servlet 3.0用于视图。 让我们从Redis / Jedis部分开始。 您可以在这些 帖子中找到有关Redis和Jed…

Socket.io 深入理解

最近在做项目优化工作时,用到了Socket.io , Socket.io 文档比较少, 结合官网介绍以及自己在项目开发中的摸索,总结如下内容; Socket.io将Websocket和轮询 (Polling)机制以及其它的实时通信方式封装成了通用…

python填表_小Python填表得到d

我正在尝试使用Scrapy从网站自动下载数据。在我要做的是:使用我的凭据登录网站通过在“RIC”行中写入代码并选择感兴趣的时段来选择我想要的数据单击“获取数据”后,将生成.csv文件,我可以从“下载/”url下载该文件,其中我的所有文…

如何使用异步Servlet来提高性能

这篇文章将描述一种性能优化技术,适用于与现代Web应用程序相关的常见问题。 如今的应用程序不再只是被动地等待浏览器发起请求,而是希望自己开始通信。 一个典型的示例可能涉及聊天应用程序,拍卖行等–共同点是以下事实:大多数时间…

我理解中的“大前端”/“大无线”

本文内容较长,大概需要15分钟时间阅读。 内容包含五部分:前言,NodeJS职能变化,ReactNative的大规模应用,专门的架构组职能,总结。主要是介绍我所在团队最近的一些变化和思考。 更多信息可以加入我的小密圈关…

STM32之Systick(系统时钟滴答定时器)

systick定时器有两个可选的时钟源,一个是外部时钟源(STCLK,等于HCLK/8),另一个是内核时钟(FCLK,等于HCLK)。假若你选择内核时钟,并将HCLK频率设置为72MHz的话&#xff0c…

Dirichlet分布

1.预备知识 Beta分布函数是一种定义在实数区间[0,1]的特殊函数,它是二项式分布的共轭分布;与Beta分布相同,Dirichlet分布也是定义在实数区间[0,1]的概率度量函数,Dirichlet分布是多项式分布的共轭分布,Dirichlet分布的…

python编程制作接金币游戏_pygame学习笔记(6):完成一个简单的游戏

学了这么长时间的Pygame,一直想写个游戏实战一下。看起来很简单的游戏,写其来怎么这么难。最初想写个俄罗斯方块,想了很长时间如何实现,想来想去,也没写出来,于是干脆下载别人的代码来读。后来,…

Spring:使基于Java的配置更加优雅

大家好,我很久没有写新文章了。 积累了很多资料,需要在不久的将来在我的博客中发布。 但是现在我想谈谈Spring MVC应用程序配置。 确切地说,我想谈谈基于Java的Spring配置。 尽管在3.0版本中引入了基于Spring Java的配置,但是许多…

用观察者模式编写一个可被其他对象拓展复用自定义事件系统

观察者模式 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知 什么是观察者模式? 发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态…

布局定位

布局与定位 摆放元素 1,使用流 流实际上就是浏览器在页面上摆放HTML元素所用的方法。浏览器从HTML文件最上面开始,从上到下沿着元素流逐个显示所遇到的各个元素。 每个块元素会按它在HTML标记中出现的顺序放置在页面上。每个新的块元素会带来一个换行。并…

T - Memory and Trident CodeForces - 712B( 注意:* ++ = 的优先级

题意:有四种命令:U代表上移一个单位,D代表下移一个单位,R代表右移一个单位,L代表左移一个单位。 现在给出一串命令,问怎样修改命令中的任意一条命令,使得命令结束后重新返回原点,并且…

python语言精通_Python语言基础从入门到精通

1、python关键字False await else import passNone break except in raiseTrue class finally is returnand continue for lambda tryas def from nonlocal whileassert del global not withasync elif if or yield2、命令行参数williamdeMBP-2:~ william$ python -c "imp…

休眠事实:了解刷新操作顺序很重要

Hibernate将开发人员的思维方式从思考SQL转变为思考对象状态转换。 根据Hibernate Docs,实体可能处于以下状态之一: new / transient:实体不与持久性上下文关联,因为它是数据库不知道的新创建的对象。 持久性:实体与…

[HNOI2012]排队

题目描述 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检。他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的&a…

声速的测量的实验原理和应用_声速的测定实验报告心得体会

测量声速的实验报告1。提出问题如何测出声音的速度?2。猜想与假设如果在一定距离内听到声音要多少时间?3。实验步骤步骤应该就是实施实验,第三是实验器材的话,就是要秒表。4。实施实验在一个山谷中,站在距离峭壁680M的地方大叫一声&#xf…