Java 可选参数 [英] Java optional parameters

查看:36
本文介绍了Java 可选参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 Java 中使用可选参数?什么规范支持可选参数?

解决方案

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

  1. 方法重载.

    void foo(String a, Integer b) {//...}

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

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

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

  1. 可变参数.

a) 所有可选参数的类型相同:

 void foo(String a, Integer... b) {整数 b1 = b.length >0 ?b[0]:0;整数 b2 = b.length >1 ?b[1]:0;//...}foo(a");foo(a", 1, 2);

b) 可选参数的类型可能不同:

 void foo(String a, Object... b) {整数 b1 = 0;字符串 b2 = ";如果 (b.length > 0) {if (!(b[0] instanceof Integer)) {throw new IllegalArgumentException("...");}b1 = (整数)b[0];}如果 (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. Nulls.要解决之前方法的局限性,您可以允许空值,然后分析方法主体中的每个参数:

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

    foo(a", null, 2);

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

  1. 可选类.这种方法类似于空值,但对具有默认值的参数使用 Java 8 可选类:

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

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

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

    更新:Java 8 包括开箱即用的 java.util.Optional 类,因此在 Java 8 中没有必要为此特殊原因使用 guava.方法名称是不过有点不同.

  2. 构建器模式.构建器模式用于构造器,并通过引入单独的构建器类来实现:

    class Foo {私有最终字符串a;私有最终整数 b;Foo(String a, Integer b) {this.a = a;this.b = b;}//...}类 FooBuilder {私人字符串 a = ";私人整数 b = 0;FooBuilder setA(String a) {this.a = a;返回这个;}FooBuilder setB(Integer b) {this.b = b;返回这个;}富建(){返回新的 Foo(a, b);}}Foo foo = new FooBuilder().setA(a").build();

  3. 映射.当参数数量过多并且通常使用大多数默认值时,您可以将方法参数作为其名称/值的映射传递:

    void foo(Map 参数) {字符串 a = "";整数 b = 0;如果(parameters.containsKey(a")){if (!(parameters.get(a") instanceof Integer)) {throw new IllegalArgumentException("...");}a = (Integer)parameters.get(a");}如果(parameters.containsKey(b")){//...}//...}

    foo(ImmutableMap.of(一个",一个",b", 2,d"、值"));

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

    @SuppressWarnings("unchecked")静态 <T>T getParm(Map map, String key, T defaultValue) {返回 (map.containsKey(key)) ?(T) map.get(key) : defaultValue;}void foo(Map 参数) {String a = getParm(parameters, a", ");int b = getParm(参数,b",0);//d = ...}foo(Map.of(a", a", b",2, d", value"));

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

How do I use optional parameters in Java? What specification supports optional parameters?

解决方案

There are several ways to simulate optional parameters in Java:

  1. Method overloading.

    void foo(String a, Integer b) { //... }

    void foo(String a) { foo(a, 0); // here, 0 is a default value for b }

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

One of the limitations of this approach is that it doesn't work if you have two optional parameters of the same type and any of them can be omitted.

  1. Varargs.

a) All optional parameters are of the same type:

    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) Types of optional parameters may be different:

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

The main drawback of this approach is that if optional parameters are of different types you lose static type checking. Furthermore, if each parameter has the different meaning you need some way to distinguish them.

  1. Nulls. To address the limitations of the previous approaches you can allow null values and then analyze each parameter in a method body:

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

    foo("a", null, 2);

Now all arguments values must be provided, but the default ones may be null.

  1. Optional class. This approach is similar to nulls, but uses Java 8 Optional class for parameters that have a default value:

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

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

    Optional makes a method contract explicit for a caller, however, one may find such signature too verbose.

    Update: Java 8 includes the class java.util.Optional out-of-the-box, so there is no need to use guava for this particular reason in Java 8. The method name is a bit different though.

  2. Builder pattern. The builder pattern is used for constructors and is implemented by introducing a separate Builder class:

    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. Maps. When the number of parameters is too large and for most of the default values are usually used, you can pass method arguments as a map of their names/values:

    void foo(Map<String, Object> 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.<String, Object>of( "a", "a", "b", 2, "d", "value"));

    In Java 9, this approach became easier:

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

Please note that you can combine any of these approaches to achieve a desirable result.

这篇关于Java 可选参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆