java中重载 参数顺序
期望将过多的参数传递给Java方法的问题之一是,该方法的客户端很难确定它们是否以适当的顺序传递了适当的值。 在以前的文章中,我描述了如何使用自定义类型 , 参数对象和构建器来解决此问题。 解决此问题的另一种方法,也是本文的主题,是为客户提供最适合他们需求的相同方法的重载版本 。 就像我以前关于过多的方法参数的文章一样,我将在本篇文章的结尾简要讨论这种方法的优缺点。
Java支持方法重载 ,即能够通过其方法签名区分同一方法的不同版本。 请注意,作为两种方法之间唯一的不同,不同的返回类型通常不足以实现重载。
可能由于多种原因而应用方法重载。 重载方法的一个目标可能是在不同类型上支持相同的功能(尤其是如果无法使用泛型来允许该方法支持不同类型,或者如果在泛型可用之前编写了这些方法)。 考虑到此意图的方法重载示例包括String.valueOf(boolean) , String.valueOf(char) , String.valueOf(double) , String.valueOf(long) , String.valueOf(Object)和其他一些版本String.valueOf
重载在其他一些类型上。
选择重载方法的另一个原因是,客户端可以调用方法的适当版本以仅提供必要的参数。 例如,可以这样做,以消除客户端为不适用或可选的参数传递一个或多个null的需要。 为实现此目的而编写的重载方法的示例包括Date类的构造函数,例如Date(int,int,int) , Date(int,int,int,int,int)和Date(int,int,int,int,int,int,int) ,int,int) 。
这种具有许多重载版本构造器(每个构造器都接受不同数量的参数)的方法称为伸缩构造器,并已被某些人称为反模式 。 实际上,这种伸缩式构造方法的缺点是Josh Bloch着重于《 有效Java第二版》第2项中的Builder模式的推动力之一。 顺便说一句, Date
类还提供了一些重载的构造函数,它们也旨在实现上述目标,例如,允许从String构造Date 。
提供多个重载方法和构造函数以接受一组减少的必需或最低适用参数的想法可以应用于我们自己的类。 下一个代码清单为原始方法提供了太多的参数,然后显示了该方法的一些潜在的重载版本,这些版本接受减少的参数集。 为了便于讨论,我们假设未在覆盖的方法签名之一中提供的任何参数是可选的,或不适用于该特定方法调用。 该代码上的注释说明了每种方法如何做出某些假设以减少其参数数量。
方法过多和版本重载的参数示例
/*** Generates and provides an instance of the Person class. This method* expects all characteristics of the populated Person instance and so any* optional or not applicable characteristics must be passed in as null.* * @param lastName* @param firstName* @param middleName* @param salutation* @param suffix* @param streetAddress* @param city* @param state* @param isFemale* @param isEmployed* @param isHomeOwner* @return A Person object.*/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...}/*** Generate and provide an instance of the Person class that has only a first* and last name and address information. This method does not make any* assumptions about other characteristics of the instantiated Person, but* simply leaves those attributes undefined.* * @param lastName* @param firstName* @param streetAddress* @param city* @param state* @return Instance of Person class with no middle name and without specified* gender, employment status, or home ownership status.*/public Person createPerson(final String lastName,final String firstName,final String streetAddress,final String city,final String state){// implementation goes here...}/*** Generate and provide instance of Person class with no middle name and* with specified home ownership status. All instances of Person returned* from this method are assumed to be Female and to be Employed, but have no* address information.* * @param lastName* @param firstName* @param homeOwnerStatus* @return Instance of Person with provided first name, provided last name,* and provided home ownership status, and assumed to be an employed* female.*/public Person createPerson(final String lastName,final String firstName,final boolean homeOwnerStatus){// implementation goes here...}
重载方法的Javadoc描述介绍了它们的不同方法。 第一种方法期望提供Person
实例的所有特征,而对于不适用的参数,则需要提供null(例如,如果一个人没有中间名,或者该中间名对于在此中的使用不重要)案件)。 第二个重载版本不希望提供所有参数,并假定它不希望的参数在返回的Person
实例中仍未定义。
第三种重载方法版本大多是针对其特性未提供明确参数的假设。 例如,假设实例化的Person
既是女性又是受雇人员。 第三种方法无法实例化男性或失业人员。 这说明了通过简单的方法重载处理太多参数的缺点(仅根据参数的数量和类型重载具有相同名称的方法)。
我在这篇文章中没有显示我自己的任何构造函数,但是同样的问题和方法也适用于上面的非构造函数方法。 同样,重载的构造函数与重载的非构造函数方法具有相同的优点和缺点。
优势与优势
Java中的方法重载似乎很容易理解,并且在包括C / C ++和C#在内的多种语言中很常见。 当参数是可选的时,方法重载特别有效。 例如,在我的示例中,重载方法消除了传递中间名的期望,比重载方法假设特定实例是受雇女性要有效得多。 如果中间名,性别和就业状况的特征确实是可选的,那么根本不假设任何一个值都比假定一个特定的值更好。
成本与劣势
明智的方法重载可能很有用,但方法重载必须谨慎使用。 “ 学习Java语言”线索的“ 类和对象”课程的“ 定义方法”部分警告:“应谨慎使用重载的方法,因为它们会使代码的可读性大大降低。”
即使是我简单的三个示例,也显示了如何使重载Swift变得难以阅读。 在我的示例中,该代码的阅读者或用户要么需要仔细阅读Javadoc并相信它是最新且准确的,要么需要深入研究实现以查看该方法的每个重载版本的功能。 在IDE中,尤其是如果同一方法有许多重载版本,则很难确定哪种方法适用于给定的情况。
我的示例表明,必须使用注释来解释重载方法所做的假设。 如前所述,如果开发人员不费心地编写它们,它们可能会过时,不准确甚至不可用。 能够以不同的方式命名方法显然更好,这样方法的名称可以提供有关其假设的线索,而不是仅依赖于Javadoc。 以这种方式使用命名方法将是以后的主题,但是根据定义为方法使用不同的名称将使其不再重载。
我的示例显示了使用带有相同类型的多个参数的重载(同名)方法的特定限制。 第三个示例接受一个boolean
,但是只有Javadoc和该参数的名称可以告诉我它适用于房屋所有权,而不适用于性别或就业状况。 我无法提供类似的重载方法来获取相同的名称信息和一个boolean
,该boolean
表示不同的内容(例如性别或工作状态),因为该方法的签名与boolean
指示房屋所有权状态的方法相同。 再次可以通过使用不同命名的方法来补救,这些方法指出了它们适用于哪种布尔条件。
解决此最后提到的限制的另一种方法是使用自定义类型和/或参数对象,并提供接受这些自定义类型的不同组合的重载方法的各种版本。 这在下一个代码清单中与自定义类型一起显示,该代码显示了对于这三种情况,当这三种情况各自不需要共享相同的类型时,对于所有三种情况,可以通过单个第三个参数来重载接受两个名称字符串的方法。
自定义类型启用改进的方法/构造函数重载
public Person createPerson(final String lastName,final String firstName,final HomeownerStatus homeOwnership){// implementation goes here...}public Person createPerson(final String lastName,final String firstName,final Gender gender){// implementation goes here...}public Person createPerson(final String lastName,final String firstName,final EmploymentStatus employmentStatus){// implementation goes here...}
我要提到的最后一个缺点与使用方法重载来解决与方法或构造函数的参数过多相关的问题有关,这种方法将来可能导致大量的维护工作。 每当添加或删除或什至更改该类的属性(构造函数)或方法的参数,甚至可能需要单独检查并可能更改多个构造函数和/或方法。
结论
重载方法确实有其位置,并且可以是为客户端提供更易理解和可读的方法和构造函数的便捷方法。 但是,我发现这种方法是“最佳”方法的频率比已经介绍的其他一些方法( 自定义类型 , 参数对象 , 构建器 )少,并且比我打算介绍的某些方法(例如不同的方法和相同方法和构造函数的显式命名版本)。 通过将方法重载与其他一些方法结合使用,可以减少方法重载方法的某些局限性和缺点。 例如,使用自定义类型和参数对象可以显着提高一个人的能力,使其能够更狭窄地调整重载方法或构造函数的各种版本以使其符合要求。
翻译自: https://www.javacodegeeks.com/2013/10/too-many-parameters-in-java-methods-part-4-overloading.html
java中重载 参数顺序