2176 votes

Ne le support de Java valeurs de paramètre par défaut?

Je suis tombé sur certains de code Java qui a la structure suivante:

public MyParameterizedFunction(String param1, int param2)
{
    this(param1, param2, false);
}

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
    //use all three parameters here
}

Je sais qu'en C++, je peux assigner un paramètre à une valeur par défaut. Par exemple:

void MyParameterizedFunction(String param1, int param2, bool param3=false);

Java soutenir ce genre de syntaxe? Existe-il des raisons à cela à deux étapes, la syntaxe est-elle préférable?

1236voto

Kathy Van Stone Points 10310

Non, la structure est la façon dont Java gère (qui est, avec la surcharge place des paramètres par défaut).

Pour les constructeurs, Voir Efficace Java: Langage de Programmation Guide de l' Élément 1 de la pointe (tenir compte de la statique de l'usine de méthodes à la place des constructeurs) si une surcharge se complique. Pour les autres méthodes, en renommant certains cas, ou à l'aide d'un paramètre de l'objet peut vous aider. C'est quand vous avez assez de complexité que la distinction est difficile. Un cas déterminé l'endroit où vous avez à les différencier à l'aide de l'ordre des paramètres, et non pas seulement le nombre et le type.

774voto

Eli Courtwright Points 53071

Non, mais vous pouvez utiliser le Générateur de Modèle, comme décrit dans ce Débordement de Pile réponse.

Comme décrit dans la réponse, le Générateur de Modèle vous permet d'écrire un code comme

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

dans lequel certains champs peuvent avoir des valeurs par défaut ou en option.

630voto

Vitalii Fedorenko Points 17469

Il existe plusieurs façons de simuler les paramètres par défaut en Java:

  1. La surcharge de méthode.

    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 limitations de cette approche est qu'elle ne fonctionne pas si vous avez deux options de paramètres de même type et de même 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 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 facultatifs sont de différents types, vous perdez de type statique de contrôle. En outre, si chaque paramètre est différent ce qui signifie que vous devez trouver un moyen de les distinguer.

  3. Les valeurs null. Pour surmonter les limites des approches précédentes, vous pouvez autoriser les valeurs null et puis d'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, tous les arguments des valeurs doit être fournie, mais les valeurs par défaut peut être null.

  4. Classe optionnelle. Cette approche est similaire à null, mais utilise à la goyave classe Optionnelle pour les paramètres qui ont 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());
    

    En option permet une méthode de contrat explicite pour l'appelant, toutefois, on peut trouver une telle signature trop verbeux.

  5. Le générateur de modèle. Le générateur de modèle est utilisé pour les constructeurs et est mis en œuvre par l'ajout d'une nouvelle Constructeur de la classe:

     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. Cartes. Lorsque le nombre de paramètres est trop grande et pour la plupart des valeurs par défaut sont généralement utilisés, vous pouvez passer des arguments de méthode comme 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 = (String)parameters.get("a");
        }
        if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 
    

Veuillez noter que vous pouvez combiner ces approches pour atteindre le résultat souhaité.

375voto

Rob H Points 5599

Malheureusement, non.

94voto

ebelisle Points 639

Malheureusement, oui.

void MyParameterizedFunction(String param1, int param2, bool param3=false) {}

pourrait être écrit en Java 1.5:

void MyParameterizedFunction(String param1, int param2, Boolean... params) {
    assert params.length <= 1;
    bool param3 = params.length > 0 ? params[0].booleanValue() : false;
}

Mais si vous devez ou non dépend de la façon dont vous vous sentez sur le compilateur de générer un

new Boolean[]{}

pour chaque appel.

Pour plusieurs defaultable paramètres:

void MyParameterizedFunction(String param1, int param2, bool param3=false, int param4=42) {}

pourrait être écrit en Java 1.5:

void MyParameterizedFunction(String param1, int param2, Object... p) {
    int l = p.length;
    assert l <= 2;
    assert l < 1 || Boolean.class.isInstance(p[0]);
    assert l < 2 || Integer.class.isInstance(p[1]);
    bool param3 = l > 0 && p[0] != null ? ((Boolean)p[0]).booleanValue() : false;
    int param4 = l > 1 && p[1] != null ? ((Integer)p[1]).intValue() : 42;
}

Cela correspond syntaxe C++, qui permet uniquement les paramètres par défaut à la fin de la liste des paramètres.

Au-delà de la syntaxe, il y a une différence lorsque ce fut le moment de l'exécution de la vérification du type de defaultable paramètres et C++, les vérifie lors de la compilation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X