Question Paramètres optionnels Java


Comment utiliser les paramètres optionnels en Java? Quelle spécification prend en charge les paramètres facultatifs?


621
2018-06-08 16:12


origine


Réponses:


Varargs pourrait le faire (d'une certaine manière). A part cela, toutes les variables dans la déclaration de la méthode doivent être fournies. Si vous voulez qu'une variable soit facultative, vous pouvez surcharger la méthode en utilisant une signature qui ne nécessite pas le paramètre.

private boolean defaultOptionalFlagValue = true;

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

public void doSomething() {
    doSomething(defaultOptionalFlagValue);
}

410
2018-06-08 16:14



Il existe plusieurs façons de simuler des paramètres facultatifs dans Java:

  1. Méthode de surcharge.

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

    Une des limites de cette approche est qu'elle ne fonctionne pas si vous avez deux paramètres optionnels du même type et que l'un d'entre eux peut être omis.

  2. Varargs.

    a) Tous les paramètres optionnels sont du même 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) Les types de paramètres optionnels peuvent être différents:

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

    Le principal inconvénient de cette approche est que si les paramètres optionnels sont de types différents, vous perdez la vérification de type statique. De plus, si chaque paramètre a une signification différente, vous avez besoin d'un moyen de les distinguer.

  3. Nuls Pour résoudre les limitations des approches précédentes, vous pouvez autoriser les valeurs NULL, puis analyser chaque paramètre dans un corps de méthode:

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

    Maintenant, toutes les valeurs des arguments doivent être fournies, mais celles par défaut peuvent être nulles.

  4. Classe optionnelle Cette approche est similaire aux valeurs null, mais utilise la classe Java 8 Optional pour les paramètres ayant une valeur par défaut:

    void foo(String a, Optional<Integer> bOpt) {
        Integer b = bOpt.isPresent() ? bOpt.get() : 0;
        //...
    }
    
    foo("a", Optional.of(2));
    foo("a", Optional.<Integer>absent());
    

    Facultatif rend un contrat de méthode explicite pour un appelant, cependant, on peut trouver une telle signature trop verbeuse.

    Mise à jour: Java 8 inclut la classe java.util.Optional out-of-the-box, donc il n'y a pas besoin d'utiliser goyave pour cette raison particulière dans java 8. Le nom de la méthode est un peu différent cependant.

  5. Modèle de constructeur. Le modèle de générateur est utilisé pour les constructeurs et est implémenté en introduisant une classe Builder séparée:

     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();
    
  6. Plans. Lorsque le nombre de paramètres est trop élevé et que la plupart des valeurs par défaut sont généralement utilisées, vous pouvez passer les arguments de la méthode sous la forme d'une carte de leurs noms / valeurs:

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

Veuillez noter que vous pouvez combiner n'importe laquelle de ces approches pour obtenir un résultat souhaitable.


1389
2017-10-21 01:16



Vous pouvez utiliser quelque chose comme ceci:

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

le params La variable est optionnelle. Il est traité comme un tableau nullable d'objets.

Bizarrement, je n'ai rien trouvé à ce sujet dans la documentation, mais ça marche!

Ceci est "nouveau" dans Java 1.5 et au-delà (pas supporté dans Java 1.4 ou plus tôt).

Je vois l'utilisateur bhoot mentionné cela aussi ci-dessous.


93
2017-12-03 21:41



Il y a des paramètres optionnels avec Java 5.0. Déclarez simplement votre fonction comme ceci:

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

vous pourriez appeler avec doSomething(); ou doSomething(true); à présent.


84
2018-04-02 12:02



Malheureusement, Java ne supporte pas les paramètres par défaut directement.

Cependant, j'ai écrit un ensemble d'annotations JavaBean, et l'un d'entre eux supporte les paramètres par défaut comme suit:

protected void process(
        Processor processor,
        String item,
        @Default("Processor.Size.LARGE") Size size,
        @Default("red") String color,
        @Default("1") int quantity) {
    processor.process(item, size, color, quantity);
}
public void report(@Default("Hello") String message) {
    System.out.println("Message: " + message);
}

Le processeur d'annotation génère les surcharges de méthode pour prendre en charge correctement cela.

Voir http://code.google.com/p/javadude/wiki/Annotations

Exemple complet à http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExemple


47
2018-06-08 17:00



Il n'y a pas de paramètres optionnels en Java. Ce que vous pouvez faire, c'est surcharger les fonctions et passer les valeurs par défaut.

void SomeMethod(int age, String name) {
    //
}

// Overload
void SomeMethod(int age) {
    SomeMethod(age, "John Doe");
}

43
2018-06-08 16:18



VarArgs et la surcharge ont été mentionnés. Une autre option est un modèle Builder, qui ressemblerait à ceci:

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

Bien que ce modèle serait plus approprié lorsque vous avez besoin de paramètres facultatifs dans un constructeur.


21
2018-06-08 17:05