什么规范支持可选参数?
在 Java 中有几种方法可以模拟可选参数:
void foo(String a, Integer b) { //… }
void foo(String a) { foo(a, 0); // 这里,0 是 b 的默认值 }
富(“一”,2);富(“一”);
这种方法的一个限制是,如果您有两个相同类型的可选参数并且其中任何一个都可以省略,则它不起作用。
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);
b) 可选参数的类型可能不同:
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");
这种方法的主要缺点是,如果可选参数的类型不同,您将失去静态类型检查。此外,如果每个参数具有不同的含义,您需要一些方法来区分它们。
void foo(String a, Integer b, Integer c) { b = b != null ? 乙:0;c = c != 空?c:0;//… }
foo(“a”, null, 2);
现在必须提供所有参数值,但默认值可能为空。
void foo(String a, Optional bOpt) { Integer b = bOpt.isPresent() ?bOpt.get() : 0; //… }
foo(“a”, Optional.of(2)); foo(“a”, Optional.absent());
Optional 使调用者的方法契约明确,但是,人们可能会发现这样的签名过于冗长。
更新:Java 8 包含java.util.Optional开箱即用的类,因此在 Java 8 中出于这个特殊原因不需要使用 guava。但是方法名称有点不同。
java.util.Optional
生成器模式。 builder 模式用于构造函数,通过引入一个单独的 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 参数) { String a = “”; 整数 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> T getParm(Map<String, Object> map, String key, T defaultValue) { return (map.containsKey(key)) ? (T) map.get(key) : defaultValue; } void foo(Map<String, Object> parameters) { String a = getParm(parameters, "a", ""); int b = getParm(parameters, "b", 0); // d = ... } foo(Map.of("a","a", "b",2, "d","value"));
请注意,您可以结合使用这些方法中的任何一种来获得理想的结果。