本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接
如何使用 Java 中的可选参数?可选参数有什么规范么?
一定程度上来讲, varargs
(即长度可变的参数)可以做到这一点。除此之外,必须提供方法声明中的所有变量。如果想让变量是可选的,那么可以通过重载的方式,此时重载的方法是不带参数的。
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
复制代码
可以通过以下几种方式来模拟 Java 中的可选参数:
void foo(String a, Integer b) {
//...
}
void foo(String a) {
foo(a, 0); // b 的默认值为 0
}
foo("a", 2);
foo("a");
复制代码
该方法存在的局限性是:如果有两个类型相同的可选参数,且其中任意一个都可以忽略,那么它就会失效。
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");
复制代码
该方法存在的不足:若可选参数类型不同,此时静态类型检查就将失效。此外,如果每个参数的含义都不同,那么就需要通过其他的方式来对他们进行区分。
针对以上几种方法的局限性,可以使用空值( null
),然后再继续分析方法体中的每个参数;
void foo(String a, Integer b, Integer c) {
b = b != null ? b : 0;
c = c != null ? c : 0;
//...
}
foo("a", null, 2);
复制代码
此时必须提供所有的参数值,但是他们的缺省值可以为 null
。
该方法类似于使用空值的方法,但 Java 8 中允许使用可选类作为参数默认值;
void foo(String a, Optional bOpt) {
Integer b = bOpt.isPresent() ? bOpt.get() : 0;
//...
}
foo("a", Optional.of(2));
foo("a", Optional.absent());
复制代码
通过使用构造器,同时引入一个单独的 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();
复制代码
当参数过多,且大多数默认值通常都被使用时,可以将方法参数作为它们的名称/值得映射传递给它们;
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 种使用可选参数的一些方法了,你可以通过对他们进行有机组合,从而达到你想要的结果。
自 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