Java prend-il en charge les valeurs de paramètres par défaut?

1661

Je suis tombé sur du code Java qui avait 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 attribuer à un paramètre une valeur par défaut. Par exemple:

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

Java prend-il en charge ce type de syntaxe? Y a-t-il des raisons pour lesquelles cette syntaxe en deux étapes est préférable?

gnavi
la source
85
Non. Cependant, le modèle Builder peut vous aider.
Dave Jarvis
50
Cette fonctionnalité me manque vraiment. Cela aide beaucoup lors de la modification du code existant pour prendre un paramètre supplémentaire à une fonction ou un constructeur
Jatin
4
@Jatin Avec le refactoring Eclipse "Modifier la signature de méthode", vous pouvez ajouter un paramètre et fournir une valeur par défaut que les invocateurs existants utiliseront.
Erwin Bolwidt du
2
@ErwinBolwidt Merci. J'utilise Android Studio, et il a également la possibilité de refactoriser la méthode et de fournir des valeurs par défaut. Plutôt utile.
Jatin
3
@temporary_user_name public MyParameterizedFunction(String param1, int param2)est une déclaration de constructeur, pas de méthode.
Mario Ishac

Réponses:

955

Non, la structure que vous avez trouvée est la façon dont Java la gère (c'est-à-dire avec surcharge au lieu des paramètres par défaut).

Pour les constructeurs, reportez -vous à Astuce 1 du Guide de langage de programmation efficace (Considérez les méthodes d'usine statiques au lieu des constructeurs) si la surcharge devient compliquée. Pour d'autres méthodes, renommer certains cas ou utiliser un objet paramètre peut aider. C'est lorsque vous avez suffisamment de complexité que la différenciation est difficile. Un cas précis est celui où vous devez différencier en utilisant l'ordre des paramètres, pas seulement le nombre et le type.

Kathy Van Stone
la source
135
@JarrodRoberson: Les méthodes d'usine statiques ne sont pas plus nuisibles que new. Ils sont utilisés tout le temps dans un nouveau code. Les constructeurs d'objets de valeur simples sont souvent le résultat d'une ingénierie excessive.
Lii
12
@JarrodRoberson: Moyen intéressant de forcer une utilisation correcte via le compilateur, merci pour le partage! Suggestion amicale pour les futurs articles: 300 lignes de code source non commenté sont probablement un peu trop digérées pour la plupart des gens (le code est plus difficile à lire qu'à écrire, après tout). Merci encore!
Christian Aichinger
17
@JarrodRoberson: Nice, avec impatience! Ce que je voulais communiquer: en tant que lecteur de votre blog, un exemple de 50 lignes avec une brève description textuelle de ce qui se passe m'aiderait à plus de 300 lignes sans contexte.
Christian Aichinger
8
@ user177800 Pas d'accord - les méthodes statiques si elles sont écrites en tant que fonctions pures sont parfaitement correctes. C'est quand une fonction statique mute l'état qu'elle devient un problème ...
Levi Fuller
642

Non, mais vous pouvez utiliser le modèle de générateur , comme décrit dans cette réponse Stack Overflow .

Comme décrit dans la réponse liée, le modèle de générateur vous permet d'écrire du 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 être facultatifs.

Eli Courtwright
la source
142
Enfin, un excellent exemple de moins de 2 pages du modèle Builder.
Nevvermind
14
Je suis curieux cependant, pourquoi avons-nous besoin d'une classe de générateur lors de l'utilisation du modèle de générateur. Je pensais à Student s1 = new Student (). Name ("Spicolo"). Age (16) .motto ("Aloha, Mr Hand);
ivanceras
52
@ivanceras: Cela est pertinent lorsque les classes ont des champs obligatoires et que vous ne voulez pas pouvoir instancier ces classes dans un état non valide. Donc, si vous venez de le dire, Student s1 = new Student().age(16);cela vous laisserait avec un étudiant sans nom, ce qui pourrait être mauvais. Si ce n'est pas mauvais, alors votre solution est très bien.
Eli Courtwright
57
@ivanceras: une autre raison est que vous voudrez peut-être que votre classe soit immuable après la construction, donc vous ne voudriez pas de méthodes qui changent ses valeurs.
Jules
3
@ivanceras: J'ai utilisé les constructeurs pour 3 choses - en éliminant les arguments multiples et l'initialisation courante, l'immuabilité et, surtout, je pense que pour valider l'objet de domaine dans la méthode build () .Pourquoi créer une instance d'objet si elle n'est pas valide.Vous pouvez également surcharger l'électricité statique méthodes d'usine comme dans le cas ci-dessus buildFreshman (), buildSenior () etc
Abhijeet Kushe
485

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

  1. 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 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 limites des approches précédentes, vous pouvez autoriser les valeurs nulles, 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 facultative. Cette approche est similaire aux valeurs null, mais utilise la classe facultative Java 8 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());

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

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

     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 important et que la plupart d'entre eux sont généralement utilisés par défaut, vous pouvez passer des 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 = (String)parameters.get("a");
        } else 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.

Vitalii Fedorenko
la source
1
Bonne explication. Je n'ai jamais vu de valeurs de retour utilisées comme ça. Pour 5) que return thisfaire? De plus, FooBuilder().setA("a").build();puisque (par définition) le constructeur est appelé en premier et FooBuilder()renvoie une valeur, cela ne signifie- .setA("a"):t-il pas qu'il n'a pas la chance d'être appelé?
Celeritas
3
@Celeritas return thisrenvoie le même objet sur lequel la méthode a été appelée (dans l'exemple, FooBuilder). Cela permet de chaîner des méthodes dans une instruction agissant sur le même objet: new FooBuilder().setA(..).setB(..).setC(..)etc, au lieu d'appeler chaque méthode dans une instruction distincte.
ADTC
2
@Celeritas new FooBuilder()renvoie un FooBuilderobjet sur lequel la setAméthode est appelée. Comme setBn'est pas appelé, this.bconserve la valeur par défaut. Enfin la buildméthode est appelée sur cet FooBuilderobjet. La buildméthode crée et renvoie un Fooobjet qui est défini sur la variable Foo foo. Notez que l' FooBuilderobjet n'est stocké dans aucune variable.
ADTC
L'annotation peut également être utilisée pour créer des paramètres par défaut et est très utile lorsqu'elle est requise pour les collections polymorphes. docs.oracle.com/javase/tutorial/java/annotations/declaring.html
Martin Spamer
1
Plus de 900 votes positifs sur la même réponse à travers deux questions. Je suis impressionné: stackoverflow.com/questions/965690/java-optional-parameters/…
AdamMc331
256

Malheureusement non.

Rob H
la source
34
C'est si triste? Cela introduirait des signatures de fonction potentiellement ambiguës.
Trey
69
@Trey: les langues avec des paramètres par défaut abandonnent souvent la surcharge des fonctions car elles sont alors moins convaincantes. Donc pas d'ambiguïté. À côté, Scala a ajouté la fonctionnalité en 2.8 et a résolu en quelque sorte le problème d'ambiguïté (car ils ont gardé la surcharge pour des raisons de compatibilité).
PhiLho
32
Je ne vois pas comment les valeurs par défaut des paramètres empêchent la surcharge de fonctions. C #, par exemple, autorise les remplacements et permet également les initialisations par défaut. On dirait un choix arbitraire, pas la restriction en est la raison.
FlavorScape
51
Ouais, permet de faire un compromis en obligeant le compilateur à faire un travail supplémentaire et à la place nous faire tous écrire 100 000 surcharges pour donner à nos utilisateurs de la commodité. Bonne idée.
28
@ user562566: Chaque fois que je travaille sur un projet Java, j'ai l'impression que les développeurs Java sont payés / mesurés par le nombre de lignes de code qu'ils produisent par jour
Mark K Cowan
83

Malheureusement oui.

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

pourrait être écrit en Java 1.5 comme:

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épendre de ce que vous pensez du compilateur générant un

new Boolean[]{}

pour chaque appel.

Pour plusieurs paramètres par défaut:

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

pourrait être écrit en Java 1.5 comme:

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 à la syntaxe C ++, qui autorise uniquement les paramètres par défaut à la fin de la liste des paramètres.

Au-delà de la syntaxe, il existe une différence dans le cas où le type d'exécution a vérifié les paramètres par défaut passés et le type C ++ les vérifie lors de la compilation.

ebelisle
la source
14
Intelligent, mais varargs (...) ne peut être utilisé que pour le paramètre final, ce qui est plus limitatif que les langues prenant en charge les paramètres par défaut.
CurtainDog
6
c'est intelligent mais un peu désordonné par rapport à la version C ++
Someone Somewhere
5
Java a certainement besoin de paramètres par défaut facultatifs comme C # et d'autres le permettent ... la syntaxe est évidente et je suppose qu'ils peuvent l'implémenter assez simplement même en compilant simplement toutes les combinaisons possibles ... Je ne peux pas imaginer pourquoi ils ne l'ont pas ajouté au langage encore!
jwl
10
Il ne faut jamais utiliser un assertcode en production. Jetez une exception.
Michael Dorst
5
-1 Ce n'est vraiment pas à ça que servent varargs. Ceci est un hack. - dans ce cas, l'utilisation de surcharges sera beaucoup plus lisible (ce qui est regrettable, car trois caractères supplémentaires sont plus lisibles que 5 lignes de source supplémentaires ...). - mais Java ne prend pas en charge les paramètres par défaut.
BrainSlugs83
38

Non, mais vous pouvez très facilement les émuler. Ce qui était en C ++ était:

public: void myFunction(int a, int b=5, string c="test") { ... }

En Java, ce sera une fonction surchargée:

public void myFunction(int a, int b, string c) { ... }

public void myFunction(int a, int b) {
    myFunction(a, b, "test");
}

public void myFunction(int a) {
    myFunction(a, 5);
}

Plus tôt, il a été mentionné que les paramètres par défaut provoquaient des cas ambigus de surcharge de fonctions. Ce n'est tout simplement pas vrai, nous pouvons le voir dans le cas du C ++: oui, il peut peut-être créer des cas ambigus, mais ces problèmes peuvent être facilement traités. Il n'a tout simplement pas été développé en Java, probablement parce que les créateurs voulaient un langage beaucoup plus simple que le C ++ - s'ils avaient raison, c'est une autre question. Mais la plupart d'entre nous ne pensent pas qu'il utilise Java en raison de sa simplicité.

peterh - Réintégrer Monica
la source
8
L'idée principale de la notation de valeur par défaut C # est précisément d'éviter ce codage standard et d'avoir un seul constructeur au lieu de plusieurs.
Kolya Ivankov
1
@KolyaIvankov Je ne connais pas C #, mais je connais C ++ où le raisonnement est le même. Je ne sais pas ce qui est le mieux, mais je pense qu'en fait, le même code passe-partout est généré par le compilateur dans le cas de C ++ / C # et il va dans le binaire final.
peterh
5
Chaque langage de programmation est (en particulier) un moyen d'éviter un passe-partout Assembleur, je me trompe? La question est seulement de savoir si cela donne ou non une fonctionnalité pratique.
Kolya Ivankov
2
La première phrase est une question rhétorique. Le mot «question» dans la deuxième phrase n'a rien à voir avec la question rhétorique de la première.
Kolya Ivankov
1
Plus précis: les langages sont des outils qui nous permettent d'écrire des programmes de manière à pouvoir contrôler ce qui est écrit, la compilation est un moyen de dire à une machine ce que nous en voulons. Un outil est plus utile s'il permet d'éviter les passe-partout. En effet, gnavi a demandé s'ils pouvaient éviter précisément le type de code passe-partout que vous proposez comme réponse, puisque C # le permet.
Kolya Ivankov
24

Vous pouvez le faire dans Scala, qui s'exécute sur la JVM et est compatible avec les programmes Java. http://www.scala-lang.org/

c'est à dire

class Foo(var prime: Boolean = false, val rib: String)  {}
lythique
la source
58
Apportez un tout nouveau langage pour obtenir une fonctionnalité pas si commune?
om-nom-nom
8
@ om-nom-nom: Java ne devrait jamais exister. Dire qu'une fonctionnalité n'est pas utilisée équivaut à ce que personne n'en a besoin, c'est dire que Java n'était pas populaire avant son invention signifie que Gosling ne devrait pas commencer à la concevoir.
Val
28
@Val vient de dire que c'est comme tirer sur des oiseaux avec des canons
om-nom-nom
8
cela n'a rien à voir avec la question du PO
destan
Fonctionne également à Kotlin. Et Groovy. Et C#. Et Javascript. Et presque toutes les autres langues conçues pour des personnes et des problèmes réels.
spyro
17

Non , mais la façon la plus simple de mettre en œuvre ceci est:

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    param3 = param3 == null ? false : param3;
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

ou au lieu de l' opérateur ternaire , vous pouvez utiliser if:

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    if (param3 == null) {
        param3 = false;
    }
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}
simhumileco
la source
2
Oui, cette approche semble être la meilleure des autres alternatives. Il serait quand même bien que Java adopte des valeurs par défaut; Kotlin a montré que cela peut être fait, donc je ne sais pas pourquoi Oracle n'entre pas dans l'ère moderne et continue de concevoir java comme si c'était les années 1990. : D
shevy
13

Je dirais peut-être l'évidence ici, mais pourquoi ne pas simplement implémenter le paramètre "par défaut" vous-même?

public class Foo() {
        public void func(String s){
                func(s, true);
        }
        public void func(String s, boolean b){
                //your code here
        }
}

pour la valeur par défaut, vous utiliserez soit

func("my string");

et si vous ne souhaitez pas utiliser la valeur par défaut, vous utiliserez

func("my string", false);
IronWolf
la source
11
L'affiche a demandé si ce modèle (plutôt laid) pouvait être évité ... ;-) Dans les langages plus modernes (comme c #, Scala), vous n'avez pas besoin de ces surcharges supplémentaires qui ne font que créer plus de lignes de code. Jusqu'à un certain point, vous pouvez utiliser des varargs en attendant (static int max (int ... array) {}), mais ce n'est qu'une solution de contournement très laide.
Offler
2
La surcharge n'est pas laide et présente de nombreux avantages, tels que différents appels de méthode avec différentes signatures peuvent effectuer différentes fonctionnalités. //This is better public class Foo() { /* This does something */ public void func(String s){ //do something } /* This does something else with b */ public void func(String s, boolean b){ // b was passed } } //Than this public class Foo() { /* This does something unless b = value, then it does something else */ public void func(String s, boolean b = value){ If (b){ // Do Something } else{ // Do something else } } }
Antony Booth
Eh bien, si l'on veut un comportement différent. Si la seule différence est un léger changement dans les calculs, etc., c'est certainement un gaspillage d'efforts pour créer plusieurs signatures. Les valeurs par défaut ont un sens là où vous en avez besoin ... et leur absence ne doit pas être classée comme une exigence "inutile".
Kapil
Les paramètres par défaut de @Offler n'ont rien à voir avec le "langage moderne". Je les ai utilisés dans Delphi il y a 20 ans et ils existaient probablement déjà dans Turbo Pascal.
L'incroyable
Je suis d'accord avec Offler et en désaccord avec Antony Booth. Je le trouve non seulement laid mais aussi assez inefficace. Les langages tels que ruby ​​ou python rendent trivial l'utilisation des paramètres par défaut; Je suppose que Java vous oblige à faire est de trouver (et d'utiliser) des solutions de contournement. La vérification explicite par rapport à null semble être le choix le moins laid, car je peux aussi appeler cela à partir de la ligne de commande (juste ne rien fournir, puis gérer la variante saine); l'approche de surcharge de l'opérateur semble ... très verbeuse (comme au moins +3 lignes, par rapport au null-check, et plus de lignes si le code est plus complexe).
shevy
8

Comme Scala a été mentionné, Kotlin mérite également d'être mentionné. Dans la fonction Kotlin, les paramètres peuvent également avoir des valeurs par défaut et ils peuvent même faire référence à d'autres paramètres:

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
    ...
}

Comme Scala, Kotlin fonctionne sur la JVM et peut être facilement intégré dans des projets Java existants.

mrts
la source
6

Non.

Vous pouvez obtenir le même comportement en passant un objet qui a des valeurs par défaut intelligentes. Mais encore une fois, cela dépend de votre cas.

Santosh Gokak
la source
5

Non. En général, Java n'a pas (beaucoup) de sucre syntaxique, car ils ont essayé de créer un langage simple.

tomjen
la source
26
Pas assez. La vérité amère est que l'équipe était sur un calendrier serré et n'avait pas de temps pour le sucre syntaxique. Sinon, pourquoi constet gotoseraient réservés des mots clés qui ne sont pas mis en œuvre? - Surtout constquelque chose qui me manque amèrement - finalne remplace pas et ils le savaient. - Et si vous avez pris la décision consciente de ne jamais l'implémenter, gotovous n'aurez pas besoin de réserver le mot-clé. - Et plus tard dans l'équipe Java triché en rendant le Label basé breaket continueaussi puissant qu'un Pascal goto.
Martin
"Simple, orienté objet et familier" était en effet un objectif de conception - voir oracle.com/technetwork/java/intro-141325.html
mikera
1
tomjen a déclaré: "Non. En général, Java n'a pas (beaucoup) de sucre syntaxique, car ils ont essayé de créer un langage simple". Vous dites donc que la suppression de nombreuses fonctionnalités inutiles de C ++ fait de Java un langage simple, alors dites-moi pourquoi Java a des méthodes variadiques? Pourquoi a-t-il des varargs? Ce n'est pas nécessaire si vous pouvez simplement utiliser un tableau d'objets à la place, ai-je raison? Ainsi, les varargs peuvent être supprimés de la langue, car cela n'est pas nécessaire. Cela rendra Java plus simple que ce qu'il est maintenant. Ai-je raison? La surcharge peut également être supprimée, car vous avez des noms infinis pour chaque méthode.
1
et c'est pourquoi nous avons eu du printemps et des trucs qui prennent le langage simple et transforment n'importe quel vrai projet Java en un clusterfuck de syntaxe et de passe
partout
Forcer les développeurs à utiliser du code standard et des solutions de contournement compliquées n'est pas ma compréhension du mot "facile". myFunction (a, b = false, c = 3), c'est ce que j'appelle facile.
spyro
5

À la place d'utiliser:

void parameterizedMethod(String param1, int param2) {
    this(param1, param2, false);
}

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

Vous pouvez utiliser la fonctionnalité facultative de java en ayant une seule méthode:

void parameterizedMethod(String param1, int param2, @Nullable Boolean param3) {
    param3 = Optional.ofNullable(param3).orElse(false);
    //use all three parameters here
}

La principale différence est que vous devez utiliser des classes wrapper au lieu de types Java primitifs pour autoriser l' nullentrée. Booleanau lieu de boolean, Integerau lieu de intet ainsi de suite.

Viktor Taranenko
la source
4

Il n'est pas pris en charge mais il existe plusieurs options comme l'utilisation d'un modèle d'objet de paramètre avec du sucre de syntaxe:

public class Foo() {
    private static class ParameterObject {
        int param1 = 1;
        String param2 = "";
    }

    public static void main(String[] args) {
        new Foo().myMethod(new ParameterObject() {{ param1 = 10; param2 = "bar";}});
    }

    private void myMethod(ParameterObject po) {
    }
}

Dans cet exemple, nous construisons ParameterObjectavec des valeurs par défaut et les remplaçons dans la section d'initialisation d'instance de classe{ param1 = 10; param2 = "bar";}

hoaz
la source
3

Essayez cette solution:

public int getScore(int score, Integer... bonus)
{
    if(bonus.length > 0)
    {
        return score + bonus[0];
    }

    return score;
}
Hamzeh Soboh
la source
3

Vous pouvez utiliser Java Method Invocation Builder le générateur d' pour générer automatiquement le générateur avec des valeurs par défaut.

Ajoutez simplement @GenerateMethodInvocationBuilder à la classe ou à l'interface et le @Default aux paramètres dans les méthodes où vous souhaitez des valeurs par défaut. Un générateur sera généré au moment de la compilation, en utilisant les valeurs par défaut que vous avez spécifiées avec vos annotations.

@GenerateMethodInvocationBuilder
public class CarService {
 public CarService() {
 }

 public String getCarsByFilter(//
   @Default("Color.BLUE") Color color, //
   @Default("new ProductionYear(2001)") ProductionYear productionYear,//
   @Default("Tomas") String owner//
 ) {
  return "Filtering... " + color + productionYear + owner;
 }
}

Et puis vous pouvez invoquer les méthodes.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .invoke(instance);

Ou définissez l'une des valeurs par défaut sur autre chose.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .withColor(Color.YELLOW)//
  .invoke(instance);
Tomas Bjerre
la source
2

Une approche similaire à https://stackoverflow.com/a/13864910/2323964 qui fonctionne dans Java 8 consiste à utiliser une interface avec des getters par défaut. Ce sera plus d'espaces verbeux, mais est moquable, et c'est génial lorsque vous avez un tas d'instances où vous voulez réellement attirer l'attention sur les paramètres.

public class Foo() {
    public interface Parameters {
        String getRequired();
        default int getOptionalInt(){ return 23; }
        default String getOptionalString(){ return "Skidoo"; }
    }

    public Foo(Parameters parameters){
        //...
    }

    public static void baz() {
        final Foo foo = new Foo(new Person() {
            @Override public String getRequired(){ return "blahblahblah"; }
            @Override public int getOptionalInt(){ return 43; }
        });
    }
}
Novaterata
la source
2

J'ai maintenant passé pas mal de temps à comprendre comment utiliser cela avec des méthodes qui retournent des valeurs, et je n'ai vu aucun exemple jusqu'à présent, j'ai pensé qu'il pourrait être utile d'ajouter ceci ici:

int foo(int a) {
    // do something with a
    return a;
}

int foo() {
    return foo(0); // here, 0 is a default value for a
}
AAGD
la source
1

Voici comment je l'ai fait ... ce n'est peut-être pas aussi pratique que d'avoir un `` argument facultatif '' contre votre paramètre défini, mais cela fait le travail:

public void postUserMessage(String s,boolean wipeClean)
{
    if(wipeClean)
    {
        userInformation.setText(s + "\n");
    }
    else
    {
        postUserMessage(s);
    }
}

public void postUserMessage(String s)
{
    userInformation.appendText(s + "\n");
}

Remarquez que je peux invoquer le même nom de méthode avec juste une chaîne ou que je peux l'invoquer avec une chaîne et une valeur booléenne. Dans ce cas, définir wipeClean sur true remplacera tout le texte de mon TextArea par la chaîne fournie. Définir wipeClean sur false ou le laisser de côté tout simplement ajoute le texte fourni à TextArea.

Notez également que je ne répète pas le code dans les deux méthodes, j'ajoute simplement la fonctionnalité de pouvoir réinitialiser le TextArea en créant une nouvelle méthode avec le même nom uniquement avec le booléen ajouté.

En fait, je pense que c'est un peu plus propre que si Java fournissait un «argument facultatif» pour nos paramètres, car nous aurions alors besoin de coder pour les valeurs par défaut, etc. Dans cet exemple, je n'ai pas à me soucier de tout cela. Oui, j'ai ajouté une autre méthode à ma classe, mais c'est plus facile à lire à long terme à mon humble avis.

Michael Sims
la source
1

NON, mais nous avons une alternative sous la forme d'une surcharge de fonction.

appelé quand aucun paramètre n'est passé

void operation(){

int a = 0;
int b = 0;

} 

appelé lorsqu'un paramètre "a" a été transmis

void operation(int a){

int b = 0;
//code

} 

appelé lorsque le paramètre b est passé

void operation(int a , int b){
//code
} 
Umair Khalid
la source
1

Il y a une demi-douzaine ou mieux de problèmes comme celui-ci, finalement, vous arrivez au modèle d'usine statique ... consultez l'API crypto pour cela. Trier difficile à expliquer, mais pensez-y de cette façon: si vous avez un constructeur, par défaut ou autre, la seule façon de propager l'état au-delà des accolades est soit d'avoir un isValid booléen; (avec le null comme valeur par défaut v constructeur échoué) ou lève une exception qui n'est jamais informative lors du retour des utilisateurs sur le terrain.

Code correct, bon sang, j'écris des milliers de constructeurs de lignes et je fais ce dont j'ai besoin. Je trouve que l'utilisation d'isValid dans la construction d'objets - en d'autres termes, les constructeurs à deux lignes - mais pour une raison quelconque, je migre vers le modèle d'usine statique. Il me semble que vous pouvez faire beaucoup de choses si vous dans un appel de méthode, il y a toujours des problèmes de synchronisation () mais les valeurs par défaut peuvent être mieux "substituées" (plus sûres)

Je pense que ce que nous devons faire ici est de résoudre le problème de null comme valeur par défaut vis-à-vis de quelque chose String one = new String (""); en tant que variable membre, puis en vérifiant la valeur null avant d'attribuer la chaîne passée au constructeur.

Très remarquable la quantité d'informatique brute et stratosphérique réalisée à Java.

C ++ et ainsi de suite a des bibliothèques de fournisseurs, oui. Java peut les distancer sur des serveurs à grande échelle car il s'agit d'une énorme boîte à outils. Étudiez les blocs d'initialisation statiques, restez avec nous.

Nicholas Jordan
la source
1

Il n'est pas pris en charge en java comme dans d'autres langues par exemple. Kotlin.

Virendra Pal Singh
la source
0

Vous pouvez utiliser les éléments suivants-

public void mop(Integer x) {
  // Define default values
        x = x == null ? 200 : x;
}
Sobhit Sharma
la source