Java supporta i valori dei parametri predefiniti?


1661

Mi sono imbattuto in alcuni codici Java che avevano la seguente struttura:

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

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

So che in C ++ posso assegnare a un parametro un valore predefinito. Per esempio:

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

Java supporta questo tipo di sintassi? Ci sono dei motivi per cui è preferibile questa sintassi in due passaggi?


85
No. Tuttavia, il modello Builder può essere d'aiuto.
Dave Jarvis,

50
Mi manca davvero questa funzione. Aiuta molto quando si modifica il codice esistente per prendere un parametro extra per una funzione o un costruttore
Jatin

4
@Jatin Con il refactoring "Cambia la firma del metodo" di Eclipse è possibile aggiungere un parametro e fornire un valore predefinito che verranno utilizzati dai chiamanti esistenti.
Erwin Bolwidt,

2
@ErwinBolwidt Grazie. Sto usando Android Studio e ha anche la possibilità di refactoring del metodo e fornire valori predefiniti. Abbastanza utile
Jatin,

3
@temporary_user_name public MyParameterizedFunction(String param1, int param2)è una dichiarazione di costruzione, non di metodo.
Mario Ishac,

Risposte:


955

No, la struttura che hai trovato è come Java lo gestisce (vale a dire con sovraccarico invece di parametri predefiniti).

Per i costruttori, consultare il suggerimento dell'articolo 1 della Guida linguistica effettiva: programmazione 1 (considerare i metodi statici di fabbrica anziché i costruttori) se il sovraccarico si sta complicando. Per altri metodi, può essere utile rinominare alcuni casi o utilizzare un oggetto parametro. Questo è quando hai abbastanza complessità che la differenziazione è difficile. Un caso definito è quello in cui devi differenziare usando l'ordine dei parametri, non solo il numero e il tipo.



135
@JarrodRoberson: i metodi statici di fabbrica non sono più dannosi di new. Essi sono utilizzati tutto il tempo nel nuovo codice. I costruttori di oggetti di valore semplice sono spesso il risultato di un eccesso di ingegneria.
Lii,

12
@JarrodRoberson: modo interessante di forzare un uso corretto tramite il compilatore, grazie per la condivisione! Suggerimento amichevole per i post futuri: 300 righe di codice sorgente non commentato sono probabilmente un po 'più difficili da digerire per la maggior parte delle persone (il codice è più difficile da leggere che da scrivere, dopo tutto). Grazie ancora!
Christian Aichinger,

17
@JarrodRoberson: Bello, non vedo l'ora! Cosa volevo comunicare: come lettore del tuo blog, un esempio di 50 righe con una breve descrizione testuale di ciò che sta accadendo mi aiuterebbe più di 300 righe senza contesto.
Christian Aichinger,

8
@ user177800 Non sono d'accordo: i metodi statici se scritti come funzioni pure vanno benissimo. È quando una funzione statica muta afferma che diventano un problema ...
Levi Fuller,

642

No, ma puoi usare il Builder Pattern , come descritto in questa risposta Stack Overflow .

Come descritto nella risposta collegata, il Builder Pattern ti consente di scrivere codice simile

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

in cui alcuni campi possono avere valori predefiniti o essere facoltativi.


142
Finalmente un ottimo esempio in meno di 2 pagine del modello Builder.
nevvermind

14
Sono curioso però, perché abbiamo bisogno di una classe builder quando si utilizza il modello builder. Stavo pensando a Student s1 = new Student (). Name ("Spicolo"). Age (16) .motto ("Aloha, Mr Hand);
ivanceras,

52
@ivanceras: è rilevante quando le classi hanno campi obbligatori e non si desidera poter creare un'istanza di tali classi in uno stato non valido. Quindi, se hai appena detto, Student s1 = new Student().age(16);ciò ti lascerebbe con uno Studente senza nome, il che potrebbe essere negativo. Se non è male, allora la tua soluzione va bene.
Eli Courtwright,

57
@ivanceras: un altro motivo è che potresti desiderare che la tua classe sia immutabile dopo la costruzione, quindi non vorrai metodi in essa che ne cambino i valori.
Jules,

3
@ivanceras: ho usato Builders per 3 cose: eliminare l'argomento multiplo e l'inizializzazione fluida, l'immutabilità e, soprattutto, mi sento di convalidare l'oggetto di dominio nel metodo build (). Perché creare un'istanza di oggetto se non è valida. Puoi anche sovraccaricare statico metodi di fabbrica come nel caso sopra buildFreshman (), buildSenior () ecc.
Abhijeet Kushe

485

Esistono diversi modi per simulare i parametri predefiniti in Java:

  1. Metodo sovraccarico.

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

    Una delle limitazioni di questo approccio è che non funziona se si hanno due parametri opzionali dello stesso tipo e uno qualsiasi di essi può essere omesso.

  2. Varargs.

    a) Tutti i parametri opzionali sono dello stesso tipo:

    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) I tipi di parametri opzionali possono essere diversi:

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

    Lo svantaggio principale di questo approccio è che se i parametri opzionali sono di tipi diversi si perde la verifica del tipo statico. Inoltre, se ogni parametro ha un significato diverso, è necessario un modo per distinguerli.

  3. Null. Per affrontare i limiti degli approcci precedenti è possibile consentire valori null e quindi analizzare ogni parametro in un corpo del metodo:

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

    Ora devono essere forniti tutti i valori degli argomenti, ma quelli predefiniti potrebbero essere nulli.

  4. Classe opzionale. Questo approccio è simile ai null, ma utilizza la classe opzionale Java 8 per i parametri che hanno un valore predefinito:

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

    Facoltativo rende esplicito un contratto di metodo per un chiamante, tuttavia, è possibile trovare tale firma troppo dettagliata.

  5. Modello del costruttore. Il modello builder viene utilizzato per i costruttori e viene implementato introducendo una classe Builder separata:

     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. Mappe. Quando il numero di parametri è troppo grande e per la maggior parte di essi vengono solitamente utilizzati valori predefiniti, è possibile passare argomenti del metodo come una mappa dei loro nomi / valori:

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

Si noti che è possibile combinare uno di questi approcci per ottenere un risultato desiderabile.


1
Buona spiegazione Non ho mai visto valori di ritorno usati in questo modo. Per 5) cosa return thisfanno? Inoltre, FooBuilder().setA("a").build();poiché (per definizione) il costruttore viene chiamato per primo e FooBuilder()restituisce un valore, questo non significa .setA("a"):che non abbia la possibilità di essere chiamato?
Celeritas,

3
@Celeritas return thisrestituisce lo stesso oggetto su cui è stato chiamato il metodo (nell'esempio FooBuilder). Ciò consente il concatenamento di metodi in un'istruzione che agisce sullo stesso oggetto: new FooBuilder().setA(..).setB(..).setC(..)ecc. Invece di chiamare ciascun metodo in un'istruzione separata.
ADTC

2
@Celeritas new FooBuilder()restituisce un FooBuilderoggetto su cui setAviene chiamato il metodo. Come setBnon viene chiamato, this.bmantiene il valore predefinito. Alla fine il buildmetodo viene chiamato su questo FooBuilderoggetto. Il buildmetodo crea e restituisce un Foooggetto impostato sulla variabile Foo foo. Si noti che l' FooBuilderoggetto non è memorizzato in nessuna variabile.
ADTC

L'annotazione può anche essere utilizzata per creare parametri predefiniti ed è molto utile quando richiesto per le raccolte polimorfiche. docs.oracle.com/javase/tutorial/java/annotations/declaring.html
Martin Spamer,

1
Oltre 900 voti con la stessa risposta su due domande. Sono impressionato: stackoverflow.com/questions/965690/java-optional-parameters/...
AdamMc331

256

Purtroppo no.


34
È così triste? In questo modo si introducono firme di funzioni potenzialmente ambigue.
Trey,

69
@Trey: le lingue con parametri predefiniti spesso abbandonano il sovraccarico della funzione poiché è quindi meno convincente. Quindi nessuna ambiguità. Inoltre, Scala ha aggiunto la funzione in 2.8 e in qualche modo risolto il problema di ambiguità (poiché hanno mantenuto il sovraccarico per motivi di compatibilità).
PhiLho,

32
Non riesco a vedere come i valori predefiniti dei parametri impediscono il sovraccarico della funzione. C # per esempio consente le sostituzioni e consente anche le inizializzazioni predefinite. Sembra una scelta arbitraria, non la restrizione è la ragione.
FlavorScape

51
Sì, lasciamo perdere il compito di fare del compilatore un po 'di lavoro extra e invece ci fanno scrivere tutti 100000 sovraccarichi per dare agli utenti della libreria comodità. Buona idea.

28
@ user562566: Ogni volta che lavoro su un progetto Java, ho l'impressione che gli sviluppatori Java siano pagati / misurati da quante righe di codice producono al giorno
Mark K Cowan,

83

Sfortunatamente sì.

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

potrebbe essere scritto in Java 1.5 come:

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

Ma se dovresti dipendere o meno da come ti senti riguardo al compilatore che genera un

new Boolean[]{}

per ogni chiamata.

Per più parametri predefinibili:

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

potrebbe essere scritto in Java 1.5 come:

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

Ciò corrisponde alla sintassi C ++, che consente solo i parametri predefiniti alla fine dell'elenco dei parametri.

Oltre alla sintassi, c'è una differenza in cui questo ha il controllo del tipo di tempo di esecuzione per i parametri predefiniti passati e il tipo C ++ li controlla durante la compilazione.


14
Intelligente, ma varargs (...) può essere utilizzato solo per il parametro finale, che è più limitante di quello che offrono le lingue che supportano i parametri predefiniti.
CurtainDog,

6
è intelligente ma un po 'disordinato rispetto alla versione C ++
Someone Somewhere

5
Java ha sicuramente bisogno di parametri predefiniti opzionali come C # e altri consentono ... la sintassi è ovvia e presumo che possano implementarlo abbastanza semplicemente compilando tutte le possibili combinazioni ... Non riesco a immaginare perché non l'hanno aggiunto al linguaggio ancora!
jwl

10
Non si dovrebbe mai usare un assertcodice di produzione. Lancia un'eccezione.
Michael Dorst,

5
-1 Questo non è davvero ciò che varargs è per. Questo è un trucco. - in questo caso, l'uso dei sovraccarichi sarà molto più leggibile (il che è sfortunato, poiché tre caratteri extra sono più leggibili di 5 righe extra di sorgente ...). - ma Java non supporta i parametri predefiniti.
BrainSlugs83,

38

No, ma puoi emularli molto facilmente. Cosa c'era in C ++:

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

In Java, sarà una funzione sovraccarica:

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

In precedenza è stato menzionato che i parametri predefiniti hanno causato casi ambigui nel sovraccarico delle funzioni. Questo semplicemente non è vero, possiamo vedere nel caso del C ++: sì, forse può creare casi ambigui, ma questi problemi possono essere facilmente gestiti. Semplicemente non è stato sviluppato in Java, probabilmente perché i creatori volevano un linguaggio molto più semplice come lo era il C ++ - se avevano ragione, è un'altra domanda. Ma la maggior parte di noi non pensa che usi Java per la sua semplicità.


8
L'idea principale della notazione del valore di default di C # è proprio quella di evitare questa codifica della piastra di caldaia e avere un solo costruttore anziché molti.
Kolya Ivankov,

1
@KolyaIvankov Non conosco C #, ma conosco C ++ dove il ragionamento è lo stesso. Non so quale sia il migliore, ma penso che in realtà lo stesso codice boilerplate sia generato dal compilatore nel caso di C ++ / C # e stia andando nel binario finale.
Peter - Ripristina Monica il

5
Ogni linguaggio di programmazione è (in particolare) un mezzo per evitare una caldaia assembler, sbaglio? La domanda è solo se fornisce una funzionalità utile o meno.
Kolya Ivankov,

2
La prima frase è una domanda retorica. La parola "domanda" nella seconda frase non ha nulla a che fare con la domanda retorica nella prima.
Kolya Ivankov,

1
Essere più specifici: le lingue sono strumenti che ci consentono di scrivere programmi in un modo in cui possiamo avere il controllo su ciò che è scritto, la compilazione è un modo per dire a una macchina ciò che vogliamo da esso. Uno strumento è più utile se ci consente di evitare la caldaia. In effetti, gnavi ha chiesto, se possono evitare con precisione il tipo di codice del bollettino che proponi come risposta, poiché C # lo consente.
Kolya Ivankov,

24

Puoi farlo in Scala, che gira su JVM ed è compatibile con i programmi Java. http://www.scala-lang.org/

vale a dire

class Foo(var prime: Boolean = false, val rib: String)  {}

58
Portare un linguaggio completamente nuovo per ottenere una funzionalità non così comune?
om-nom-nom,

8
@ om-nom-nom: Java non dovrebbe mai esistere. Dire che una funzione non viene utilizzata equivale a non averne bisogno per nessuno significa che Java non era popolare prima che fosse inventata significa che Gosling non avrebbe dovuto iniziare a progettarla.
Val

28
@Val solo dicendo che è come sparare agli uccelli con i cannoni
om-nom-nom,

8
ciò non ha nulla a che fare con la domanda del PO
destan

Funziona anche a Kotlin. E Groovy. E C#. E Javascript. E quasi tutte le altre lingue create per persone e problemi reali.
spyro

17

No , ma il modo più semplice per implementarlo è:

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

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

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

o invece dell'operatore ternario , puoi usare if:

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

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

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

2
Sì, questo approccio sembra essere il migliore delle altre alternative. Comunque sarebbe bello per Java adottare valori predefiniti; Kotlin ha dimostrato che ciò può essere fatto, quindi non sono sicuro del perché Oracle non entri nell'era moderna e continui a progettare Java come se fosse gli anni '90. : D
shevy

13

Potrei affermare l'ovvio qui, ma perché non implementare semplicemente il parametro "predefinito" da solo?

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

per impostazione predefinita, dovresti usare entrambi

func("my string");

e se non desideri utilizzare il valore predefinito, lo utilizzeresti

func("my string", false);

11
Il poster ha chiesto se questo (piuttosto brutto) modello può essere evitato ... ;-) In linguaggi più moderni (come c #, Scala) non hai bisogno di questi sovraccarichi extra che creano solo più righe di codice. Nel frattempo puoi usare varargs (static int max (int ... array) {}), ma sono solo una soluzione molto brutta.
Offler,

2
Il sovraccarico non è brutto e ha molti vantaggi, come ad esempio le diverse chiamate di metodo con firme diverse possono eseguire funzionalità diverse. //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,

Bene, se si vogliono comportamenti diversi. Se l'unica differenza è una leggera modifica nei calcoli, ecc., È sicuramente uno sforzo per creare più firme. I valori predefiniti hanno senso dove sono necessari ... e la sua mancanza non dovrebbe essere classificata come requisito "inutile".
Kapil,

I parametri predefiniti di @Offler non hanno nulla a che fare con il "linguaggio moderno". Li ho usati a Delfi 20 anni fa e probabilmente esistevano già in Turbo Pascal.
L'incredibile gennaio

Sono d'accordo con Offler e non sono d'accordo con Antony Booth. Lo trovo non solo brutto ma anche abbastanza inefficiente. Linguaggi come ruby ​​o python rendono banale l'utilizzo di parametri predefiniti; Immagino che ciò che Java ti richiede di fare sia trovare (e usare) soluzioni alternative. Il controllo esplicito contro null sembra essere la scelta meno brutta, dal momento che posso chiamarla anche dalla riga di comando (semplicemente non fornire nulla e quindi gestire la variante sana); l'approccio di sovraccarico dell'operatore sembra ... molto dettagliato (come almeno +3 righe, rispetto al controllo null, e più righe se il codice è più complesso).
shevy

8

Come è stato menzionato Scala, vale la pena menzionare anche Kotlin . Nella funzione di Kotlin anche i parametri possono avere valori predefiniti e possono anche fare riferimento ad altri parametri:

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

Come Scala, Kotlin gira su JVM e può essere facilmente integrato in progetti Java esistenti.


6

No.

È possibile ottenere lo stesso comportamento passando un oggetto con valori predefiniti intelligenti. Ma di nuovo dipende dal tuo caso.


5

No. In generale Java non ha molto (alcun) zucchero sintattico, dal momento che hanno cercato di creare un linguaggio semplice.


26
Non proprio. L'amara verità è che la squadra aveva un programma serrato e non aveva tempo per lo zucchero sintattico. Perché altrimenti conste gotoriservare le parole chiave che nessuna implementazione? - Soprattutto constè qualcosa che mi manca amaramente - finalnon è un rimpiazzo e loro lo sapevano. - E se hai preso la decisione consapevole di non implementare mai goto, non dovrai prenotare la parola chiave. - E più tardi nel Java Team barato rendendo l'etichetta basata breake continuepotente come un Pascal goto.
Martin,

"Semplice, orientato agli oggetti e familiare" era davvero un obiettivo di progettazione - vedi oracle.com/technetwork/java/intro-141325.html
mikera,

1
tomjen ha detto: "No. In generale Java non ha molto (alcun) zucchero sintattico, dal momento che hanno cercato di creare un linguaggio semplice". Quindi stai dicendo che rimuovere molte funzionalità non necessarie dal C ++ rende Java un linguaggio semplice, quindi dimmi perché Java ha metodi variadici? Perché ha varargs? Non è necessario se si può semplicemente utilizzare una matrice di oggetti, giusto? Quindi varargs può essere rimosso dalla lingua, perché non è necessario. Ciò renderà Java più semplice di quello che è ora. Ho ragione? È inoltre possibile rimuovere il sovraccarico, poiché si hanno nomi infiniti per ciascun metodo.

1
ed è per questo che abbiamo primavera e cose che prendono il linguaggio semplice e trasformano qualsiasi vero progetto Java in un ammasso di sintassi e boilerplate :-)
matanster

Forzare gli sviluppatori al codice boilerplate e soluzioni complicate non è la mia comprensione della parola "facile". myFunction (a, b = false, c = 3), questo è ciò che chiamo facile.
spyro

5

Invece di usare:

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

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

È possibile utilizzare la funzionalità opzionale di Java utilizzando un solo metodo:

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

La differenza principale è che è necessario utilizzare le classi wrapper anziché i tipi Java primitivi per consentire l' nullinput. Booleaninvece di boolean, Integerinvece di inte così via.


4

Non è supportato ma ci sono diverse opzioni come l'uso del pattern di oggetti parametro con un po 'di zucchero di sintassi:

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

In questo esempio costruiamo ParameterObjectcon i valori predefiniti e li sovrascriviamo nella sezione di inizializzazione dell'istanza di classe{ param1 = 10; param2 = "bar";}


3

Prova questa soluzione:

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

    return score;
}

3

È possibile utilizzare Java Method Invocation Builder per generare automaticamente il builder con valori predefiniti.

Aggiungi @GenerateMethodInvocationBuilder alla classe o all'interfaccia e @Default ai parametri nei metodi in cui desideri i valori predefiniti. Un builder verrà generato al momento della compilazione, utilizzando i valori predefiniti specificati con le annotazioni.

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

E poi puoi invocare i metodi.

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

Oppure imposta uno dei valori predefiniti su qualcos'altro.

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

2

Un approccio simile a https://stackoverflow.com/a/13864910/2323964 che funziona in Java 8 consiste nell'utilizzare un'interfaccia con getter predefiniti. Questo sarà più spazioso, ma è beffardo, ed è perfetto per quando hai un sacco di casi in cui vuoi attirare l'attenzione sui parametri.

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

2

Ho trascorso un bel po 'di tempo per capire come usarlo con metodi che restituiscono valori e finora non ho visto alcun esempio, ho pensato che potesse essere utile aggiungere questo qui:

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

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

1

È così che l'ho fatto ... non è conveniente forse come avere un 'argomento opzionale' rispetto al parametro definito, ma ottiene il lavoro fatto:

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

Nota che posso invocare lo stesso nome di metodo con una sola stringa o posso invocarlo con una stringa e un valore booleano. In questo caso, l'impostazione di wipeClean su true sostituirà tutto il testo nel mio TextArea con la stringa fornita. L'impostazione di wipeClean su false o l'esclusione di tutti insieme aggiunge semplicemente il testo fornito a TextArea.

Nota anche che non sto ripetendo il codice nei due metodi, sto semplicemente aggiungendo la funzionalità di poter resettare TextArea creando un nuovo metodo con lo stesso nome solo con il booleano aggiunto.

In realtà penso che questo sia un po 'più pulito rispetto al fatto che Java fornisse un' argomento opzionale 'per i nostri parametri poiché dovremmo quindi codificare i valori predefiniti ecc. In questo esempio, non devo preoccuparmi di nulla. Sì, ho aggiunto un altro metodo alla mia classe, ma è più facile da leggere a lungo termine secondo la mia modesta opinione.


1

NO, ma abbiamo un'alternativa sotto forma di sovraccarico di funzioni.

chiamato quando nessun parametro è passato

void operation(){

int a = 0;
int b = 0;

} 

chiamato quando è stato passato un parametro "a"

void operation(int a){

int b = 0;
//code

} 

chiamato quando viene passato il parametro b

void operation(int a , int b){
//code
} 

1

Ci sono mezza dozzina o problemi migliori come questo, alla fine, arrivi al modello statico di fabbrica ... vedi l'API crypto per quello. Ordinamento difficile da spiegare, ma pensalo in questo modo: se hai un costruttore, predefinito o meno, l'unico modo per propagare lo stato oltre le parentesi graffe è o avere un valore booleano isValid; (insieme a null come valore predefinito v costruttore non riuscito) o genera un'eccezione che non è mai informativa quando viene recuperata dagli utenti sul campo.

Codice corretto, maledizione, scrivo migliaia di costruttori di linee e faccio ciò di cui ho bisogno. Trovo che usando isValid nella costruzione di oggetti - in altre parole, costruttori a due righe - ma per qualche ragione, sto migrando al modello statico di fabbrica. Sembra che tu possa fare molto se in una chiamata di metodo, ci sono ancora problemi di sincronizzazione () ma i valori predefiniti possono essere "sostituiti" meglio (più sicuri)

Penso che ciò che dobbiamo fare qui sia affrontare il problema di null come valore predefinito rispetto a qualcosa String one = new String (""); come variabile membro, quindi eseguendo un controllo per null prima di assegnare una stringa passata al costruttore.

Molto notevole la quantità di informatica grezza e stratosferica realizzata in Java.

C ++ e così via ha librerie del fornitore, sì. Java può superarli su server di grandi dimensioni grazie alla sua enorme cassetta degli attrezzi. Studia i blocchi di inizializzatori statici, resta con noi.



0

Puoi usare il seguente-

public void mop(Integer x) {
  // Define default values
        x = x == null ? 200 : x;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.