精华内容
下载资源
问答
  • 可选参数

    千次阅读 2012-06-04 23:16:15
    可选参数 By Bill Wagner March 2012   不少开发人员问我为什么C#早期版本中不支持可选参数可选参数在其它语言中展示了其很有益的特性。特别是当你写了一个有大量参数的方法,而该方法中的一部分参数有其合理...

    Justification for Names and Optional Parameters

    可选参数

    By Bill Wagner

    March 2012

     

    不少开发人员问我为什么C#早期版本中不支持可选参数。可选参数在其它语言中展示了其很有益的特性。特别是当你写了一个有大量参数的方法,而该方法中的一部分参数有其合理的默认值的情况下.基于Office APICOM组件就是一个明显的例子。

    C#直到4.0才添加该特性缘于其它方面需求更加迫切。此外,可选参数的益处也会导致一些问题。尤其是在你引入可选参数与方法过载间的交互后而愈加明显。你或许听说过来自C#小组成员如此的描述:每个新语言特性都以一些负面点开始,且一定有引人注目的方式来获得巨大的正面值。本文中,我会讨论一些约束未来组件发布、复杂代码的方式。你将了解到如何在你自己的代码中最好的避免这些隐患,也会对为何该特性缘何此时才被加入有所了解。

    方法确定规则

    下面是一个方法签名:

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter = default(NameFilter),

        CityFilter cityFilter = default(CityFilter),

        AgeFilter ageFilter = default(AgeFilter)

        )

    它看起来是在模仿过载来提供多个版本的方法。或许你觉得这是一种简化单个方法多个过载的手段。你可能认为已经为用户创建了下面这些方法:

    public static IEnumerable<Record> ApplyFilters(

        // no parms means no filter.

        )

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter = default(NameFilter)

        )

    public static IEnumerable<Record> ApplyFilters(

        CityFilter cityFilter = default(CityFilter)

        )

    public static IEnumerable<Record> ApplyFilters(

        AgeFilter ageFilter = default(AgeFilter)

        )

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter = default(NameFilter),

        CityFilter cityFilter = default(CityFilter),

        )

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter = default(NameFilter),

        AgeFilter ageFilter = default(AgeFilter)

        )

    public static IEnumerable<Record> ApplyFilters(

        CityFilter cityFilter = default(CityFilter),

        AgeFilter ageFilter = default(AgeFilter)

        )

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter = default(NameFilter),

        CityFilter cityFilter = default(CityFilter),

        AgeFilter ageFilter = default(AgeFilter)

        )

    虽然看上去可能是这样,实则不然。编译器会认为ApplyFilters方法包含几个可选参数,并且当调用该方法时为可选参数提供默认值,而不是提供了多个方法版本。所以就会出现类似下面的情况:

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter

        )

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter = default(NameFilter),

        CityFilter cityFilter = default(CityFilter),

        AgeFilter ageFilter = default(AgeFilter)

        )

    // sample call:

    ApplyFilters(new NameFilter());

    没有出现含糊不清,决定调用方法的规则是“准确与调用参数匹配的方法要优先于使用可选参数的方法”。因此,前一个方法将被选中来执行方法调用。迄今为止,都还算简单。多数开发人员都还分得清调用哪个。但我们只看到了表面。接下来把这两个方法放到同一个类中,看看下面的调用结果:

    // 假设NameFilter, CityFilter, AgeFilter 均派生自抽象基类//Filter .

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter = default(NameFilter),

        CityFilter cityFilter = default(CityFilter),

        AgeFilter ageFilter = default(AgeFilter)

        )

    {

        Console.WriteLine("First version");

        return null;

    }

     

    public static IEnumerable<Record> ApplyFilters(

        Filter filter

        )

    {

        Console.WriteLine("second version");

        return null;

    }

     

    // sample call:

    ApplyFilters(new NameFilter());

    ApplyFilters(new CityFilter());

    此时,上面两个方法调用中的参数都没有完全匹配第二个过载方法中的正式参数类型。而第二个方法调用中的参数类型与第一个方法过载定义的首参数完全吻合。此时,编译器该选谁呢?第一行将调用第一个方法(包含可选参数的);第二行调用了第二个方法. 相关规则可以参见c#规格说明书第四版中的7.5.3.2. 描述如下:出于过载方法选取的目的,任何调用中未指定值的可选参数都将从方法签名中移除。为了选择更适合的方法来调用,编译器一定会将两个过载方法看成如下的形式:

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter = default(NameFilter),

        )

    public static IEnumerable<Record> ApplyFilters(

        Filter filter

        )

    上面两个方法签名中,显然第一个方法更适合第一个调用。这个决定使得开发人员在使用有可选参数的方法时更加轻松。如果调用时使用的参数与带可选参数的方法更匹配,那就选定该方法。如果语言规范指定将参数个数作为重载规则,那可选参数就用处不大了。因为调用者为了选择期望的方法,必须严格地为每一个参数指定值。而现在的设计是优先考虑参数类型的匹配程度。

    如果你想强制编译器调用其它方法,可以在调用时指定参数名:

    // NameFilter, CityFilter, and AgeFilter all derive from

    // an abstract Filter class.

    public static IEnumerable<Record> ApplyFilters(

        NameFilter nameFilter = default(NameFilter),

        CityFilter cityFilter = default(CityFilter),

        AgeFilter ageFilter = default(AgeFilter)

        )

    public static IEnumerable<Record> ApplyFilters(

        Filter filter

        )

     

    ApplyFilters(filter: new NameFilter());

    ApplyFilters(cityFilter: new CityFilter());

    这样就可以调用我们期望的方法了。可以这样做是因为在C#语言规格说明书中7.5.3.2中的另一点说明:参数会被重新排列,所以它们就会出现在参数列表中的相同位置。

    也就是第二个调用一定会被转换成这样的形式:

    ApplyFilters(default(NameFilter), cityFilter: new CityFilter());

    编译器会参照参数列表排列调用参数顺序。一旦这样做了,你就可以轻易的分辨哪个方法更适合被调用了。这个选择背后的逻辑就是开发人员明确地指定参数,清楚地选择了应该被调用的方法。

    混合了类的继承关系及虚方法的场景中使用可选参数会更复杂一些:

    public abstract class Animal

    {

        public abstract void Feed(string food = "chow");

    }

     

    public class Cat : Animal

    {

        public override void Feed(string catfood = "cat chow")

        {

            Console.WriteLine(catfood);

        }

    }

     

    public class Dog : Animal

    {

        public override void Feed(string dogfood = "dog chow")

        {

            Console.WriteLine(dogfood);

        }

    }

    考虑如下调用:

    var d = new Dog();

    d.Feed();

    var c = new Cat();

    c.Feed();

    Animal thing = new Dog();

    thing.Feed();

    d.Feed()给狗喂狗粮。c.Feed()给猫喂猫粮。thing.Feed()则给第二只狗喂了普通食物。我们来检察一下为何会这样.

    对代码一个快速的检察结论是因为变量’thing’的静态类型(或称编译时类型)。’thing’ 的类型是Animal,因此方法Feed的可选参数默认值将从类Animal的方法声明中获得。的确如此,即使类Animal及方法Feed都是抽象的。

    接下来,让我们来把情况搞得更复杂点。在类dog中添加一个方法Feed的新过载版本:

    public void Feed(string dogfood = "dog chow", bool moist = false)

    {

        Console.WriteLine("{0} {1}", moist ? "moist" : "dry", dogfood);

    }

    这下会怎样?或许你会惊奇的发现编译器这次选择了有额外可选参数的过载版本。这是由确定方法过载版本的规则决定的。来自较多继承层级类的候选项总是会优先于来自较少继承层级类的候选项来考虑。这也包括应用的任何可选参数。这样就使其与确定其它方法过载版本的规则相一致。另外一个虚Feed方法实际上是在类Animal中声明的而不是在类Dog中。也就是说只有第二个Feed方法是在扩展类中声明的,因此应选用第二个方法。相关原则参见C#语言规格说明书中7.6.5.1.

    即使在我们考虑通过这些已经声明的方法来升级一个组件的分支前,仍有其它几个规则需要检察。现在让我们考虑一个有几个可选参数的虚方法,在类Cat上做如下修改:

    public class Cat : Animal

    {

        public override void Feed(string catfood) // parameter is not optional

        {

            Console.WriteLine(catfood);

        }

    }

    // usage:

    var c = new Cat();

    c.Feed();

    上面的c.Feed()无法编译!上面调用的方法未包括任何参数的默认值。所以编译器不会把这些参数添加到正式参数列表中。然而,如果把变量类型转换成类Animal,则调用会是这样:

    var c = new Cat();

    ((Animal)c).Feed();

    当然,类Cat中的Feed方法版本会被调用,因为它是一个虚方法。

    重写每个包含可选参数的虚方法时都应该重新声明这些可选参数,这样可以避免给调用者带来困惑。重新声明时,一定要确保同一个参数在每个重载中都使用同一个默认值。否则,上面两个调用中将使用不同的“食物”值。

    接口方法中应用默认参数的规则与上面基类方法中应用的规则非常相似:如果创建的一个过载方法与某个接口中的某个方法同名,而你已经显式地实现了接口方法,那该过载方法更容易取代接口方法被调用。

    发布新版本

    既然我们已经介绍了简单情况,让我们来检查一下当有组件新版本交付时,会发生什么。记得c#的最初目标之一就是成为一个“面向组件语言”,也就是说写的不错的程序集应该可以在其中一个单独部分安全的更新。这些语言中的新特性已经增长了应对组件更新带来变化的潜能。由于这些变化,编译时或运行时代码行为可能有所变化。编译时中断只会在开发者使用组件构建一个最新版本时出现。而运行时中断则会出现在用户已经安装了新组件并运行应用程序时出现。有些变更可能会同时引起编译时与运行时中断。

    我们来看个明显的例子:修改任意一个公共或保护方法上的参数名称,会引起一个编译时中断。不少C#开发人员不知道这样会引起多次中断。即使只在c#4.0中增加了对可选命名参数的支持,.net支持的其它语言也同时具有了该特性(最显示地是Visual Basic)。任何通过这些语言使用你的组件的,都将受到前面变化的影响。

    当然,修改参数默认值创建一个中断变化。这个变化或是引起编译时中断或是引起运行时中断,这取决于你是如何修改代码的。可选参数的默认值由编译器插入到调用站中。运行时任何使用了前期组件版本编译的方法将继续使用前期插入到调用站中的老值。然后,如果你重新编译了调用者,那默认值将改变。这种情况真的不太可能作为一个中断变化来避免,你必须做出选择:让中断在运行时被发现还是编译时。更新前编译的方法调用将继续使用老的默认值;使用新的组件版本重新编译后的方法调用将使用新的默认值。你的方法如何解释可选参数的新值与旧值取决于哪个版本改变了行为。

    前面我提到的所有这些问题,关于方法过载,基类中声明的可选参数方法,接口中声明可选参数方法所有这些均在此处适用。编辑任何参数默认值或是默认参数数量都会影响编译器对方法的选择。这不会引起运行时中断,但可能引发数量不定的编译时中断。当然调用不同的方法也会改变运行时行为。

    只是警告,但不绝对禁止

    上面介绍的内容不是说你的代码中决不要定义可选参数,或是决不要使用它。毕竟这已经是语言的一部分。但需要在有意义的地方使用这些新特性。尤其是要把这些特性的缺陷或可能引发的问题牢记于心,避免在自己的代码中出现相关问题。如果在你的方法中出现了一些随意放置的可选参数,这可能是个信号,提醒你应该在API的设计上再下些功夫。对可选参数的使用我持保守态度。使用时自问默认值是否会多次变更?或是方法只是可能需要多个过载而已?最重要的是避免在虚方法上或是接口方法中定义可选参数。


     

    展开全文
  • java方法可选参数_Java可选参数

    千次阅读 2020-07-05 23:15:52
    java方法可选参数 在Java类中设计方法时,某些参数对于其执行而言可能是可选的。 无论是在DTO,胖模型域对象还是简单的无状态服务类中,可选方法参数都是常见的。 从本文中, 您将学习如何在Java中处理可选参数 ...

    java方法可选参数

    在Java类中设计方法时,某些参数对于其执行而言可能是可选的。 无论是在DTO,胖模型域对象还是简单的无状态服务类中,可选方法参数都是常见的。

    从本文中, 您将学习如何在Java中处理可选参数 我们将专注于常规方法,具有可选字段的类构造函数,并快速查看所讨论主题的不良做法。 我们将停下来看看Java 8 Optional,并评估它是否符合我们的需求。

    让我们开始吧。

    1.可选方法参数

    您可以通过几种不同的方法来处理Java可选参数。 我将引导您从最简单到更复杂。

    @Nullable注解

    为什么不传递零值呢? 这是一个简单的解决方案,不需要任何额外的工作。 您没有任何需要作为方法参数之一的对象吗? 没问题。 只需传递null即可,编译器很高兴。

    这里的问题是可读性。 调用方法的程序员如何知道他是否可以安全地传递null? 对于哪些参数可以接受空值,哪些是必需的?

    为了清楚说明null是有效输入,可以使用@Nullable批注。

    User createUser(String name, @Nullable Email email) {
       // ...
    }

    您不同意此方法声明是不言自明的吗?

    可选参数

    尽管简单,但是null传递方法的问题在于它很容易失控。 团队可能会Swift开始过度使用它,并使代码库难以维护,并带有大量的空检查条件

    不过,还有其他选择。

    可选清单

    代替null,我们有时可以创建类的空表示。 考虑一下Java集合。 如果方法接受列表或映射,则永远不要使用null作为输入。

    空集合总是比空集合好,因为在大多数情况下,不需要任何特殊处理。

    您可能想知道为什么要浪费内存来创建空集合。 毕竟,null不会花费您任何费用。

    您的怀疑是有道理的。 幸运的是,有一个简单的解决方案。

    每当需要空的代表时,就不应创建集合的新实例。 在代码库中重复使用同一实例。

    你知道吗? Java已经具有您可以使用的所有集合的空实例。 可以在Collections实用程序类中找到它们

    User createUser(String name, List<Rights> rights) {
       // ...
    }
    import java.util.Collections;
    // ...
    create("bob", Collections.emptyList());

    空对象模式

    空集合的概念也适用于其他类。 空集合只是具有零元素的常规集合。 同样,您可以考虑应用程序中的其他对象。

    Null对象是表示缺失值的类的特殊实例。 如果某些方法希望将对象作为参数,则始终可以传递Null对象表示形式,而不必担心它将在运行时引起意外的异常。

    可选参数

    您可以通过两种方式实现Null对象模式。

    对于简单值对象,将预定义值分配给属性的默认实例就足够了。 通常,您将此Null对象公开为常量,以便可以多次重用。 例如:

    public class User {
    
       public static final User EMPTY = new User("", Collections.emptyList());
    
       private final String name;
       private final List<Rights> rights;
    
       public User(String name, List<Rights> rights) {
           Objects.requireNonNull(name);
           Objects.requireNonNull(rights);
           this.name = name;
           this.rights = rights;
       }
    
       // ...
    
    }

    如果您的Null对象还需要模仿通过方法公开的某些行为,则简单实例可能无法工作。 在这种情况下,您应该扩展类并覆盖此类方法。

    这是扩展前一个示例的示例:

    public class AnonymousUser extends User {
    
       public static final AnonymousUser INSTANCE = new AnonymousUser();
    
       private AnonymousUser() {
          super("", Collections.emptyList());
       }
    
       @Override
       public void changeName(String newName) {
           throw new AuthenticationException("Only authenticated user can change the name");
       }
    
    }

    专用的Null对象类使您可以将多个角落案例放在一个地方,这使维护更加轻松。

    方法重载

    如果您设计的方法带有可选参数,则可以公开该方法的重载版本。 每种方法应仅接受必需的参数。

    使用这种方法,您不必期望调用方将为可选参数提供默认值。 您可以通过自己的内部重载方法传递默认值。 换句话说,您对方法的调用者隐藏了可选参数的默认值。

    User createUser(String name) {
       this.createUser(name, Email.EMPTY);
    }
    
    User createUser(String name, Email email) {
       Objects.requireNonNull(name);
       Objects.requireNonNull(rights);
       // ...
    }

    重载的方法可以互相调用,但这不是强制性的。 如果更方便,则可以独立实现每种方法。 但是,通常您会验证所有参数,并将逻辑放在参数列表最长的方法中。

    值得一提的是,方法重载已在标准Java库中广泛使用。 当您学习如何设计API时,请向经验丰富的人学习。

    参数对象模式

    大多数开发人员都同意,当方法参数列表过长时,将变得难以阅读。 通常,您可以使用Parameter Object pattern处理问题。 参数对象是一个命名的容器类,它对所有方法参数进行分组。

    是否解决了可选方法参数的问题?

    不,不是。

    它只是将问题移至参数对象的构造函数。

    让我们看看如何用…解决这个更普遍的问题。

    2.可选的构造函数参数

    从带有可选参数的问题的角度来看,简单的构造函数与常规成员方法没有什么不同。 您可以成功使用我们已经在构造函数中讨论过的所有技术。

    但是,当构造函数参数列表越来越长并且其中许多是可选参数时,应用构造函数重载似乎很麻烦。

    如果您同意,则应签出Builder模式。

    建造者模式

    让我们考虑一个具有多个可选字段的类:

    class ProgrammerProfile {
    
       // required field
       private final String name;
       // optional fields
       private final String blogUrl;
       private final String twitterHandler;
       private final String githubUrl;
    
       public ProgrammerProfile(String name) {
           Objects.requireNonNull(name);
           this.name = name;
           // other fields assignment...
       }
    
       // getters
    
    }

    如果创建了一个构造函数来覆盖所有可能的带有可选参数的组合,那么最终将得到不胜枚举的清单。

    如何避免多个构造函数? 使用构建器类。

    您通常将构建器实现为它应该构建的类的内部类。 这样,两个类都可以访问其私有成员。

    看一下前面示例中的类的构建器:

    class ProgrammerProfile {
    
       // fields, getters, ...
    
       private ProgrammerProfile(Builder builder) {
           Objects.requireNonNull(builder.name);
           name = builder.name;
           blogUrl = builder.blogUrl;
           twitterHandler = builder.twitterHandler;
           githubUrl = builder.githubUrl;
       }
    
       public static Builder newBuilder() {
           return new Builder();
       }
    
       static final class Builder {
          
           private String name;
           private String blogUrl;
           private String twitterHandler;
           private String githubUrl;
    
           private Builder() {}
    
           public Builder withName(String val) {
               name = val;
               return this;
           }
    
           public Builder withBlogUrl(String val) {
               blogUrl = val;
               return this;
           }
    
           public Builder withTwitterHandler(String val) {
               twitterHandler = val;
               return this;
           }
    
           public Builder withGithubUrl(String val) {
               githubUrl = val;
               return this;
           }
    
           public ProgrammerProfile build() {
               return new ProgrammerProfile(this);
           }
    
       }
    
    }

    代替公共构造函数,我们只为内部构建器类公开一个静态工厂方法。 专用构造函数(构建器在build()方法中调用)使用构建器实例来分配所有字段并验证是否存在所有必需的值。

    一想起来,这是一种非常简单的技术。

    仅设置选定的可选参数的该构建器的客户机代码可能如下所示:

    ProgrammerProfile.newBuilder()
           .withName("Daniel")
           .withBlogUrl("www.dolszewski.com/blog/")
           .build();

    使用构建器,您可以使用对象的可选参数创建所有可能的组合。

    可选参数

    编译时安全的类生成器

    不幸的是,仅通过查看上一段落中构建器的方法,您就无法真正分辨出哪些参数是可选的,哪些是必需的。 而且,在不知不觉中您可能会偶然忽略所需的参数。

    查看以下错误使用的构建器示例

    ProgrammerProfile.newBuilder()
           .withBlogUrl("www.dolszewski.com/blog/")
           .withTwitterHandler("daolszewski")
           .build();

    编译器不会报告任何错误。 您将仅在运行时意识到缺少必需参数的问题。

    那么,您如何解决这个问题?

    您需要稍微修改构建器工厂方法,以便仅可以使用必需参数来调用它,而仅对可选参数使用左构建器方法。

    这就是您需要更改的所有内容:

    class ProgrammerProfile {
       
       // ...
    
       public static Builder newBuilder(String name) {
          return new Builder(name);
       }
    
       public static final class Builder {
    
          private final String name;
          // ...
    
          private Builder(String name) {
              this.name = name;
          }
    
          // ...
    
       }
    }

    生成器类的生成

    您可能会认为构建器需要大量代码。

    不用担心

    您不必自己键入所有代码。 所有流行的Java IDE都具有允许生成类生成器的插件。 IntelliJ用户可以检查InnerBuilder插件 ,而Eclipse爱好者可以看看Spart Builder Generator 您也可以在官方存储库中找到替代插件。

    如果您使用项目Lombok ,它还可以简化与类构建器的合作。 如果需要开始的地方,可以查看有关Lombok建筑商的简短介绍

    3. Java可选参数反模式

    在浏览网络以寻找使用Java可选参数的方法时,除了我们已经介绍的内容之外,您还可以找到一些其他建议。 让我解释一下为什么您应该将它们视为错误的方法。

    地图

    从技术上讲,方法的输入是一组键值对。 在Java中,我们有一个符合此描述的标准内置数据结构-Map。

    编译不会阻止您将HashMap <String,Object>用作所有可选方法参数的容器,但是您的常识应该如此。

    尽管您可以在HashMap中放入任何内容,但这是错误的想法。 这种方法难以理解,难以理解,并将Swift成为您维护的噩梦。

    还是不服气?

    您绝对应该考虑将您的职业转到JavaScript开发人员。 在公司哭泣要容易得多。

    Java变量

    需要明确的是,使用Java varargs绝对没有错。 如果您不知道您的方法将被调用多少个参数,那么varargs非常适合。

    但是将varargs用作单个值的容器(可能存在或不存在)是一种滥用。 这样的声明允许使用比预期更多的可选值来调用方法。 我们讨论了用于处理单个可选参数的更具描述性的方法。

    为什么不将Optional作为方法参数?

    最后,最有争议的方法-Java 8 Optional作为方法输入。 我已经写了一篇关于可选用例的文章 ,其中还介绍了方法参数。 让我扩展您在那里可以找到的内容。

    内存使用情况

    创建Optional类的实例时,必须为其分配内存。 尽管使用Optional.empty()访问的空可选实例是可重用的单例(就像我们已经讨论过的空集合一样),但非空实例将占用操作内存。

    如果将此方法与其他方法进行比较,仅出于调用将立即解开对象的方法的目的而使用Optional工厂方法包装对象就没有意义。

    但是,如今,垃圾收集器可以很好地处理短寿命的物品。 内存分配没什么大不了的。 我们还有其他缺点吗?

    可选参数

    铭记读者

    代码的可读性如何?

    createProfile("Daniel", Optional.of("www.dolszewski.com/blog/"),
           Optional.of("daolszewski"), Optional.of("https://github.com/danielolszewski"));

    也许这只是个人喜好问题,但对于许多开发人员而言,多个Optional工厂调用会分散您的注意力。 阅读器代码中的噪音。 但同样,这只是一个口味问题。 让我们找到更令人信服的东西。

    可选参数

    Java语言设计师的意见

    Oracle公司Java语言架构师Brian Goetz 曾表示 ,将Optional添加到标准库中时要考虑方法的结果,而不是方法的输入。

    但是软件开发人员是叛逆者,不喜欢听当局的话。 这种说法似乎也很微弱。 我们必须更深入。

    可选参数

    Optional是否解决了可选参数问题?

    如果您有这样的方法声明:

    doSomethingWith(Optional<Object> parameter);

    您应该期望多少输入?

    该参数可以是包装值或空的可选实例。 答案是2,对吗?

    错误。

    真正的答案是3,因为您还可以将null用作参数。 当您不知道谁将成为您的API的调用者时,您应该对输入具有有限的信任。

    在这种情况下,在处理参数之前,应检查Optional是否不等于null,然后检查该值是否存在。 非常复杂,您不同意吗?

    我敢肯定我还没有穷尽这个话题。 由于这是Java编程的潜在圣战之一,因此您应该形成自己的见解。 如果要向Optional的参数列表中添加某些内容作为方法参数,请在注释中分享您的想法。 非常受欢迎。

    结论

    让我们回顾一下我们学到的东西。 Java无法为方法参数设置默认值。 该语言为我们提供了许多其他可选参数来处理可选参数。

    这些替代方法包括@Nullable批注,空对象,方法重载和参数对象模式。 我们还熟悉具有多个可选字段的对象的类构建器。 最后,我们回顾了常见的不良做法和潜在的滥用行为。

    如果您觉得这篇文章有帮助,请与您的关注者分享。 我也很想知道您的想法,欢迎提出所有意见。

    翻译自: https://www.javacodegeeks.com/2018/11/java-optional-parameters.html

    java方法可选参数

    展开全文
  • Java方法的可选参数 可变参数

    万次阅读 2018-11-07 13:13:21
    Java方法的可选参数 可变参数

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                   

    突然之间想看一下JAVA中有没有C++的可选参数这一性质。

    试了一下还真可以:

    public class Select {
    public void getFwp(int i, int j, String... m) {
       if (m.length != 0) {
        System.out.println(m.length);
        System.out.println(m[0]);
        System.out.println("hk");
       }
       System.out.println(i);
       System.out.println(j);

    }

    public static void main(String[] args) {
       Select s = new Select();
       s.getFwp(1, 2);
       s.getFwp(1, 2, "sdfsadf");
       s.getFwp(1, 2, "sdfsadf1", "sfasdf");
    }
    }

    这里感觉m就是一个数组。

               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    展开全文
  • 参考文章:python 函数参数(必选参数、默认参数、可选参数、关键字参数)
    1. 默认参数增加 (x=None), if x:
      能选择是否执行对x的操作
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      参考文章:python 函数参数(必选参数、默认参数、可选参数、关键字参数)
    展开全文
  • flutter可选参数传值

    千次阅读 2019-12-28 14:20:53
    Dart可选参数方法的写法! 一, 可选参数的方法 有两种, 1,大括号{}包围的。 特点:实现方法时,可以指定具体传递某一个参数。 2,中括号[]包围的。 特点,多个可选参数时,默认按照前后顺序传递。 共同点:必填...
  • Dart可选参数方法的写法!

    千次阅读 2019-04-07 15:11:37
    可选参数的方法 有两种, 1,大括号{}包围的。 特点:实现方法时,可以指定具体传递某一个参数。 2,中括号[]包围的。 特点,多个可选参数时,默认按照前后顺序传递。 共同点:必填的参数,必须要在可选参数的前面...
  • dart 可选参数

    千次阅读 2018-09-11 13:32:12
    可选参数其实有两种含义 可选的具名参数 什么是具名?看代码 // 定义了一个这样的函数 void enableFlags(bool bold, bool hidden) { // ... } // 假如参数很多,类型相近,用的时候就不知道哪个参数对应...
  • 可选参数与命名参数

    千次阅读 2017-12-14 10:18:29
    一、可选参数: 调用方法时,常常给某个参数传送相同的值。例如,这可能是一个布尔值,以控制方法操作中的不重要部分: public List GetWords( string sentence,bool capitalizeWords) { ... } 无论给...
  • GO-如何设置可选参数

    千次阅读 2020-03-26 15:04:51
    什么是可选参数(optional parameter)? 可能很多人没明白什么是可选参数可选参数即我们可以设置也可以不设置的参数,如果我们不设置,则会使用默认值。 在JAVA中我们可以用函数重载(overloading)来实现可选参数(如...
  • 可选参数 和 TryParse用法(C#)

    千次阅读 2016-03-08 11:41:57
    可选参数有一些注意点: 1.可选参数一定程度上解脱了一些情况下必须重载的需求。 2.可选参数一定要放在所有的参数最后。 3.可选参数可以有多个,但都必须排列放在所有参数的最后。 4.方法的所有参数都可以是可选参数...
  • TypeScript入门-5.可选参数

    千次阅读 2017-01-20 14:15:27
    TypeScript入门-5.可选参数
  • 第四章:TypeScript参数的可选参数

    千次阅读 2019-01-21 17:11:59
    可选参数是指: 在方法的参数声明后面用问号来标明此参数为可选参数 function test(a:string, b?:string, c:string = "jojo"){ } 看到b后面的问号没?这个就是可选参数啦 如果b没传,我们是不能读取b的...
  • Go中的可选参数

    千次阅读 2020-02-04 12:19:07
    Go可以有可选参数吗? 还是可以只定义两个具有相同名称和不同数量参数的函数?
  • 参考:...必参...
  • /** * npm上模块安装 * 1.npm install @types/mysql --save * 2.npm install mysql... * 1)可选参数的可选性 ? 继承了c#语言的特性, */ function testJs(n:string, age? : number): string { return n + age; ...
  • js 自定义方法 设置可选参数的方法

    万次阅读 2016-10-20 20:48:15
    js 自定义方法 设置可选参数的方法php有个很方便的用法是在定义函数时可以直接给参数设默认值,如:function simue ($a=1,$b=2){ return $a+$b; } echo simue(); //输出3 echo simue(10); //输出12 echo simue(10,...
  • 1、根据方法的参数类型或者参数数量来定义可选参数: 编辑器根据参数类型判断调用哪个重载版本编辑器根据参数数量判断调用哪个重载版本 2、在定义方法的时候就已经赋值的方法参数,在调用该方法的时候可以不带参数...
  • Dart之 可选参数

    千次阅读 2019-05-21 14:26:53
    一般都是使用的可选命名参数类型,因为可选命名参数可以不用按位置进行传参,使用起来更加灵活 而可选位置参数只能按可选位置的顺序进行传参,使用起来不是很灵活 ...
  • 可选参数的存在,可以极大的降低代码的重复冗余。在数据库开发中,也是如此。现在针对MSSQL中存储过程的可选参数的定义和使用进行基本的介绍,留作备忘。
  • TypeScript基础入门 - 函数 - 可选参数和默认参数 项目实践仓库 https://github.com/durban89/typescript_demo.git tag: 1.2.0 为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都能直接运行看到...
  • java 不固定参数 / 可选参数介绍

    万次阅读 2014-05-30 22:41:34
    java的函数与js的函数相比,传递参数严谨,也就没有js那样灵活多变…… 虽然不能达到js那样灵活,但是...另一种方法可以控制传递参数的可选参数个数…… 例: public void testMethod(String... params){  
  • react-router 4.0 如何匹配可选参数

    千次阅读 2018-05-27 15:07:32
    在react-router 2.0中可选参数是这样写的&lt;Route path='/index(/:hello)' /&gt;而在react-4.0中你会惊喜的发现这种写法没用了,今天采坑碰到纪律一下要写成这样&lt;Route path='/index/:hello?' /&...
  • 可选参数及命名实参在一起

    千次阅读 2013-08-25 22:00:08
    可选参数和命名实参是C#4.0新增的特性。 本文将对可选参数和命名实参做个简单的介绍。之所以放一块来介绍,是因为两者经常成对出现,这样就可以在实例中将两者结合起来进行演示。 不过一开始,还是会分开对可选...
  • .NET 4 可选参数和命名参数

    千次阅读 2012-11-08 11:31:16
    可选参数允许为方法的一些参数提供默认值,并允许仗用者重载类型,因此,即使 只有一个方法,也能处理所有变体。下面是一个例子: public void CreateUser(string firstname, string lastname, bool isAdmin, bool ...
  • 在go语言中,有时候会...这个时候可以通过重构为一个符合结构类型,既可以变相实现可选参数,也可以实现命名实参的功能。 package main import ( "time" "log" ) type serverOption struct { address string
  • Java方法的可选参数(可变参数)

    万次阅读 2012-07-23 15:13:08
    突然之间想看一下JAVA中有没有C++的可选参数这一性质。 试了一下还真可以: public class Select { public void getFwp(int i, int j, String... m) {  if (m.length != 0) {  System.out.println(m....
  • C#可选参数的使用方法

    千次阅读 2013-05-02 10:58:31
    .net framework 4.0新增加了可选参数的支持,其实很简单,只要给参数赋个默认值就可以了 如下 static string GetStr(string s = "a", int i = 10, string r = "rrrr") { return s + i + r; } 调用时,...
  • 【单选题】定义函数时,可选参数必须定义在非可选参数的后面。 【单选题】以下for循环语句执行后,输出结果的最后一行是() for i in range(1,3): for j in range(1,3): print(i*j) 【单选题】下面程序循环次数为: s=...
  • vue路由参数可选 参数可有可无

    千次阅读 2018-02-01 15:29:39
    参数后面使用 ?... ’ ,将 id 设置为可选参数 { name: "index", path: '/p/:id?', component: resolve =>void(require(['../components/admin/layout/index.vue'], resolve)) } // == { path: '/p/:id?',
  • demo:新闻首页的不同分类的新闻列表描述:只有最新新闻不需要根据分类去查询,其他的分类下的新闻都需要添加查询条件cid,所以cid是一个可选参数,如何处理?1.定义一个空列表存放查询条件filter = []2.对参数做判断...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 941,039
精华内容 376,415
关键字:

可选参数