web-dev-qa-db-fra.com

Java paramètres facultatifs

Comment utiliser des paramètres optionnels en Java? Quelle spécification supporte les paramètres optionnels?

741
Mike Pone

varargs pourrait le faire (d'une certaine manière). En dehors de cela, toutes les variables de la déclaration de la méthode doivent être fournies. Si vous souhaitez qu'une variable soit facultative, vous pouvez surcharger la méthode à l'aide d'une signature qui ne nécessite pas le paramètre.

private boolean defaultOptionalFlagValue = true;

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

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

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

  1. Méthode surchargée.

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

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

  2. Varargs.

    a) Tous les paramètres facultatifs 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 facultatifs 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 facultatifs 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. Nulls. Pour remédier aux 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 d'argument doivent être fournies, mais les valeurs par défaut peuvent être nulles.

  4. Classe facultative. Cette approche est similaire aux valeurs nulles, mais utilise Java 8. Classe facultative 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. Toutefois, cette signature peut être trop détaillée.

    Mise à jour: Java 8 inclut la classe Java.util.Optional prête à l'emploi. Il n'est donc pas nécessaire d'utiliser guava pour cette raison particulière dans Java 8. La méthode Le nom est un peu différent cependant.

  5. Pattern Builder. Le pattern Builder 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. Maps. Lorsque le nombre de paramètres est trop important et que la plupart des valeurs par défaut sont généralement utilisées, vous pouvez passer les arguments de méthode sous forme de mappage 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")); 
    

    Dans Java 9, cette approche est devenue plus facile:

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

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

1559
Vitalii Fedorenko

Vous pouvez utiliser quelque chose comme ceci:

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

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

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

Ceci est "nouveau" dans Java 1.5 et versions ultérieures (non pris en charge dans Java 1.4 ou une version antérieure).

Je vois que l'utilisateur bhoot a également mentionné cela ci-dessous.

101
theninjagreg

Il existe des paramètres facultatifs 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[0] : false;
}

vous pouvez appeler avec doSomething(); ou doSomething(true); maintenant.

100
bhoot

Malheureusement, Java ne prend pas directement en charge les paramètres par défaut.

Cependant, j'ai écrit un ensemble d'annotations JavaBean et l'un d'eux prend en charge les paramètres par défaut tels que:

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 cette opération.

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

Exemple complet sur http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample

49

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

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

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

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 soit plus approprié lorsque vous avez besoin de paramètres optionnels dans un constructeur.

21
Yishai

Dans JDK> 1.5, vous pouvez l'utiliser comme ceci.

public class NewClass1 {

    public static void main(String[] args) {

        try {
            someMethod(18); // Age : 18
            someMethod(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);
        }
    }
}
14
az3

Cela dépend de ce que vous voulez atteindre, la surcharge de méthodes ou de varargs devrait résoudre la plupart des scénarios. Voici quelques bons exemples d'utilisation:

http://blog.sleekface.com/in/Java-core/method-with-optional-parameters/

mais gardez à l'esprit de ne pas trop utiliser la méthode surchargée. cela apporte de la confusion.

8
Marc

Version courte :

Utilisation de trois points:

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

(basé sur la réponse de @ VitaliiFedorenko)

6
T.Todua

Vous pouvez faire quelque chose en utilisant une méthode surchargée comme celle-ci.

 public void load(String name){ }

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

Aussi, vous pouvez utiliser l'annotation @Nullable

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

passez simplement null comme premier paramètre.

Si vous passez la même variable de type, vous pouvez utiliser cette

public void load(String name...){}
5
Ishan Fernando

Surcharger, c'est bien, mais s'il y a beaucoup de variables qui nécessitent une valeur par défaut, vous obtiendrez:

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) {  }

Je suggère donc d'utiliser l'argument de variable fourni par Java. Voici un lien pour l'explication.

2
Jigar Shah

Java supporte maintenant les options en 1.8, je suis bloqué dans la programmation sur Android, donc j'utilise des valeurs nulles jusqu'à ce que je puisse refactoriser le code pour utiliser des types facultatifs.

Object canBeNull() {
    if (blah) {
        return new Object();
    } else {
        return null;
    }
}

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

Les arguments par défaut ne peuvent pas être utilisés en Java. Où en C #, C++ et Python, on peut les utiliser ..

En Java, il faut utiliser 2 méthodes (fonctions) au lieu d'une avec les paramètres par défaut.

Exemple:

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-

1
Parvinder Singh

Vous pouvez utiliser une classe qui fonctionne beaucoup comme un générateur pour contenir vos valeurs facultatives comme celle-ci.

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

Utiliser comme

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

La sortie est

someString = something, someInt = 5

Pour ignorer toutes les valeurs facultatives, vous devez l'appeler comme foo(o -> {}); ou si vous préférez, vous pouvez créer une seconde méthode foo() qui ne prend pas les paramètres facultatifs.

En utilisant cette approche, vous pouvez spécifier des valeurs facultatives dans n’importe quel ordre sans aucune ambiguïté. Vous pouvez également avoir des paramètres de classes différentes, contrairement à varargs. Cette approche serait encore meilleure si vous pouvez utiliser des annotations et une génération de code pour créer la classe Options.

1
rybai

C'est une vieille question, peut-être même avant que le type optionnel réel ait été introduit, mais de nos jours, vous pouvez prendre en compte quelques éléments: - surcharge de méthode use - type optionnel utilisé qui évite de passer par NULL Le type facultatif a été introduit dans Java 8 avant il était généralement utilisé par des bibliothèques tierces telles que Google's Guava. L'utilisation facultative en tant que paramètres/arguments peut être considérée comme une utilisation excessive, l'objectif principal étant de l'utiliser comme heure de retour.

Réf.: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-Java.html

0
xproph

Nous pouvons créer des paramètres facultatifs en surchargeant la méthode ou en utilisant DataType ...

| * | Méthode surchargée:

RetDtaTyp NamFnc(String NamPsgVar)
{
    // |* CodTdo *|
    return RetVar;
}

RetDtaTyp NamFnc(String NamPsgVar)
{
    // |* CodTdo *|
    return RetVar;
}

RetDtaTyp NamFnc(int NamPsgVar1, String NamPsgVar2)
{
    // |* CodTdo *|
    return RetVar;
}

Le moyen le plus simple est

| * | DataType ... peut être un paramètre optionnel

RetDtaTyp NamFnc(int NamPsgVar, String... SrgOpnPsgVar)
{
    if(SrgOpnPsgVar.length == 0)  SrgOpnPsgVar = DefSrgVar; 

    // |* CodTdo *|
    return RetVar;
}

0
Sujay U N