Java 中的可选参数 | Java Debug 笔记

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接

问题

如何使用 Java 中的可选参数?可选参数有什么规范么?

回答

回答 1

一定程度上来讲, varargs (即长度可变的参数)可以做到这一点。除此之外,必须提供方法声明中的所有变量。如果想让变量是可选的,那么可以通过重载的方式,此时重载的方法是不带参数的。

   private boolean defaultOptionalFlagValue = true;

public void doSomething(boolean optionalFlag) {
    ...
}

public void doSomething() {
    doSomething(defaultOptionalFlagValue);
}
复制代码

回答 2

可以通过以下几种方式来模拟 Java 中的可选参数:

  1. 方法重载
   void foo(String a, Integer b) {
    //...
}

void foo(String a) {
    foo(a, 0); // b 的默认值为 0
}

foo("a", 2);
foo("a");
复制代码

该方法存在的局限性是:如果有两个类型相同的可选参数,且其中任意一个都可以忽略,那么它就会失效。

  1. 长度可变的参数
  • 所有可选参数类型相同;
   void foo(String a, Integer... b) {
    Integer b1 = b.length > 0 ? b[0] : 0;
    Integer b2 = b.length > 1 ? b[1] : 0;
    //...
}

foo("a");
foo("a", 1, 2);
复制代码
  • 可选参数类型可能不同;
   void foo(String a, Object... b) {
    Integer b1 = 0;
    String b2 = "";
    if (b.length > 0) {
        if (!(b[0] instanceof Integer)) { 
            throw new IllegalArgumentException("...");
        }
        b1 = (Integer)b[0];
    }
    if (b.length > 1) {
        if (!(b[1] instanceof String)) { 
            throw new IllegalArgumentException("...");
        }
        b2 = (String)b[1];
        //...
    }
    //...
}

foo("a");
foo("a", 1);
foo("a", 1, "b2");
复制代码

该方法存在的不足:若可选参数类型不同,此时静态类型检查就将失效。此外,如果每个参数的含义都不同,那么就需要通过其他的方式来对他们进行区分。

  1. 空值

针对以上几种方法的局限性,可以使用空值( null),然后再继续分析方法体中的每个参数;

   void foo(String a, Integer b, Integer c) {
    b = b != null ? b : 0;
    c = c != null ? c : 0;
    //...
}

foo("a", null, 2);
复制代码

此时必须提供所有的参数值,但是他们的缺省值可以为 null

  1. 可选类

该方法类似于使用空值的方法,但 Java 8 中允许使用可选类作为参数默认值;

   void foo(String a, Optional bOpt) {
    Integer b = bOpt.isPresent() ? bOpt.get() : 0;
    //...
}

foo("a", Optional.of(2));
foo("a", Optional.absent());
复制代码
  1. 构造器模式

通过使用构造器,同时引入一个单独的 Builder 类来实现;

   class Foo {
    private final String a; 
    private final Integer b;

    Foo(String a, Integer b) {
        this.a = a;
        this.b = b;
    }

    //...
}

class FooBuilder {
    private String a = ""; 
    private Integer b = 0;

    FooBuilder setA(String a) {
        this.a = a;
        return this;
    }

    FooBuilder setB(Integer b) {
        this.b = b;
        return this;
    }

    Foo build() {
        return new Foo(a, b);
    }
}

Foo foo = new FooBuilder().setA("a").build();
复制代码
  1. Maps

当参数过多,且大多数默认值通常都被使用时,可以将方法参数作为它们的名称/值得映射传递给它们;

   void foo(Map parameters) {
    String a = ""; 
    Integer b = 0;
    if (parameters.containsKey("a")) { 
        if (!(parameters.get("a") instanceof Integer)) { 
            throw new IllegalArgumentException("...");
        }
        a = (Integer)parameters.get("a");
    }
    if (parameters.containsKey("b")) { 
        //... 
    }
    //...
}

foo(ImmutableMap.of(
    "a", "a",
    "b", 2, 
    "d", "value")); 
复制代码

Java 9 中,使用如下方法可以简化该操作:

   @SuppressWarnings("unchecked")
static  T getParm(Map map, String key, T defaultValue)
{
    return (map.containsKey(key)) ? (T) map.get(key) : defaultValue;
}

void foo(Map parameters) {
    String a = getParm(parameters, "a", "");
    int b = getParm(parameters, "b", 0);
    // d = ...
}

foo(Map.of("a","a",  "b",2,  "d","value"));
复制代码

以上就是 6 种使用可选参数的一些方法了,你可以通过对他们进行有机组合,从而达到你想要的结果。

回答 3

自 Java 1.5 开始,就存在可选参数,你可以像如下方式来声明你的方法:

   public void doSomething(boolean... optionalFlag) {
    //  默认为 "false"
    //boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
复制代码

然后你就既可以调用 doSomething(),也可以调用 doSomething(true) 了。

出处

文章翻译自 Stack Overflow: Java optional parameters

你可能感兴趣的:(java,参数,java)