如何在Java中使用可选参数?

什么规格支持可选参数?

1315184 次浏览

varargs可以(在某种程度上)做到这一点。除此之外,必须提供方法声明中的所有变量。如果您希望变量是可选的,您可以使用不需要参数的签名重载方法。

private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {...}
public void doSomething() {doSomething(defaultOptionalFlagValue);}

Java中没有可选参数。您可以做的是重载函数,然后传递默认值。

void SomeMethod(int age, String name) {//}
// Overloadvoid SomeMethod(int age) {SomeMethod(age, "John Doe");}

已经提到了VarArgs和重载。另一种选择是Bloch Builder模式,如下所示:

 MyObject my = new MyObjectBuilder().setParam1(value).setParam3(otherValue).setParam6(thirdValue).build();

尽管这种模式最适合您在构造函数中需要可选参数时。

Java5.0有可选参数。只需像这样声明您的函数:

public void doSomething(boolean... optionalFlag) {//default to "false"//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;}

你现在可以用doSomething();doSomething(true);打电话。

你可以使用这样的东西:

public void addError(String path, String key, Object... params) {}

params变量是可选的。它被视为一个可为空的对象数组。

奇怪的是,我在留档中找不到任何关于这个的东西,但它有效!

这是Java1.5及更高版本中的“新”(Java1.4或更早版本不支持)。

我看到用户布特在下面也提到了这一点。

在JDK>1.5中,您可以这样使用它;

public class NewClass1 {
public static void main(String[] args) {
try {someMethod(18); // Age : 18someMethod(18, "John Doe"); // Age & Name : 18 & John Doe} catch (Exception e) {e.printStackTrace();}}
static void someMethod(int age, String... names) {
if (names.length > 0) {if (names[0] != null) {System.out.println("Age & Name : " + age + " & " + names[0]);}} else {System.out.println("Age : " + age);}}}

有几种方法可以模拟Java中的可选参数:

  1. 方法重载。

    tivefoo(字符串a,整数b){//整数b//取值范围//…}

    string foo(String a){//字符串大小

    foo(a,0);//这里,0是b的默认值}

    foo("a",2);foo("a");

这种方法的局限性之一是,如果您有两个相同类型的可选参数并且可以省略其中任何一个,则它不起作用。

  1. 瓦格斯。

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");

这种方法的主要缺点是,如果可选参数的类型不同,您将失去静态类型检查。此外,如果每个参数的含义不同,您需要某种方法来区分它们。

  1. 空。为了解决前面方法的局限性,您可以允许空值,然后分析方法体中的每个参数:

    tivefoo(字符串a,整数b,整数c){b=b!=null? b: 0;c=c!=null? c: 0;//…}

    foo("a", null,2);

现在必须提供所有参数值,但默认值可能为null。

  1. 可选类。此方法类似于null,但对具有默认值的参数使用Java8可选类:

    validfoo(String a,可选的bOpt){//请求参数整数b=bOpt.isPresent()?bOpt.get(): 0;//…}

    foo("a",Optional.of(2));foo("a",Optional.absent ());

    可选使方法合约对调用者显式化,但是,人们可能会发现这样的签名过于冗长。

    更新:Java8包含开箱即用的类java.util.Optional,因此在Java8中没有必要为此特殊原因使用番石榴。尽管方法名称有点不同。

  2. 生成器模式。构建器模式用于构造函数,并通过引入一个单独的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();
  3. 地图。当参数数量太大并且通常使用大多数默认值时,您可以将方法参数作为其名称/值的映射传递:

    validfoo(Map参数){//属性名字符串a="";整数b=0;if(parameters.contains键("a")){if(!(parameters.get("a")instance of Integer))抛出新的IllegalArgumentException("…");}a=(整数)parameters.get("a");}if(parameters.containsKey("b")){//…}//…}

    foo(ImMutableMap.of("a","a","b",2,"d","value");

    在Java9中,这种方法变得更容易:

    @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"));

请注意,您可以将这些方法中的任何一种结合起来以获得理想的结果。

默认参数不能在Java中使用。在C#,C++和Python中,我们可以使用它们。

在Java,我们必须使用2个方法(函数)而不是一个带有默认参数的方法。

示例:

Stash(int size);
Stash(int size, int initQuantity);

http://parvindersingh.webs.com/apps/forums/topics/show/8856498-java-how-to-set-default-parameters-values-like-c-

重载是可以的,但是如果有很多变量需要默认值,你最终会得到:

public void methodA(A arg1) {  }public void methodA(B arg2) {  }public void methodA(C arg3) {  }public void methodA(A arg1, B arg2) {  }public void methodA(A arg1, C arg3) {  }public void methodA(B arg2, C arg3) {  }public void methodA(A arg1, B arg2, C arg3) {  }

所以我建议使用Java提供的变量参数

你可以像这样使用方法重载。

 public void load(String name){ }
public void load(String name,int age){}

您也可以使用@Nullable注释

public void load(@Nullable String name,int age){}

简单地传递null作为第一个参数。

如果您传递相同类型的变量,您可以使用

public void load(String name...){}

Java现在支持1.8中的选项,我坚持在android上编程,所以我使用null,直到我可以重构代码以使用可选类型。

Object canBeNull() {if (blah) {return new Object();} else {return null;}}
Object optionalObject = canBeNull();if (optionalObject != null) {// new object returned} else {// no new object returned}

简短版本:

使用三个点

public void foo(Object... x) {String first    =  x.length > 0 ? (String)x[0]  : "Hello";int duration    =  x.length > 1 ? Integer.parseInt((String) x[1])     : 888;}foo("Hii", );foo("Hii", 146);

(基于@VitaliiFedorenko的回答)

我们可以通过方法重载或使用数据类型来制作可选参数…

|*|方法重载:

RetDataType NameFnc(int NamePsgVar){// |* Code Todo *|return RetVar;}
RetDataType NameFnc(String NamePsgVar){// |* Code Todo *|return RetVar;}
RetDataType NameFnc(int NamePsgVar1, String NamePsgVar2){// |* Code Todo *|return RetVar;}

最简单的方法是

|*|DataType…可以是可选参数

RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar){if(stringOpnPsgVar.length == 0)  stringOpnPsgVar = DefaultValue;
// |* Code Todo *|return RetVar;}

您可以使用类似于构建器的类来包含您的可选值,如下所示。

public class Options {private String someString = "default value";private int someInt= 0;public Options setSomeString(String someString) {this.someString = someString;return this;}public Options setSomeInt(int someInt) {this.someInt = someInt;return this;}}
public static void foo(Consumer<Options> consumer) {Options options = new Options();consumer.accept(options);System.out.println("someString = " + options.someString + ", someInt = " + options.someInt);}

使用like

foo(o -> o.setSomeString("something").setSomeInt(5));

输出是

someString = something, someInt = 5

要跳过所有可选值,您必须像foo(o -> {});一样调用它,或者如果您愿意,您可以创建第二个不接受可选参数的foo()方法。

使用这种方法,您可以以任何顺序指定可选值,没有任何歧义。您还可以拥有不同类的参数,这与varargs不同。如果您可以使用注释和代码生成来创建Options类,这种方法会更好。

这是一个古老的问题,甚至可能在引入实际的可选类型之前,但现在你可以考虑一些事情:-使用方法重载-使用可选类型,其优点是避免传递NULL可选类型在Java8中引入,然后通常从第三方库中使用,例如Google的Guava。使用可选作为参数/参数可以被认为是过度使用,因为主要目的是将其用作返回时间。

参考:https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html

如果你是0可以使用以下结构型式并实现或覆盖应用-基于您的要求的方法。

public abstract class Invoker<T> {public T apply() {return apply(null);}public abstract T apply(Object... params);}

如果它是一个API端点,一个优雅的方法是使用“Spring”注释:

@GetMapping("/api/foos")@ResponseBodypublic String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {return innerFunc(id);}

请注意,在这种情况下,innerFunc将需要变量,并且由于它不是api端点,因此无法使用此Spring注释使其成为可选的。参考:https://www.baeldung.com/spring-request-param