Risposte:
varargs potrebbe farlo (in un certo senso). Oltre a ciò, devono essere fornite tutte le variabili nella dichiarazione del metodo. Se si desidera che una variabile sia facoltativa, è possibile sovraccaricare il metodo utilizzando una firma che non richiede il parametro.
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
Esistono diversi modi per simulare parametri opzionali in Java:
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.
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.
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.
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.
Aggiornamento: Java 8 include la classe java.util.Optional
pronta all'uso, quindi non è necessario utilizzare guava per questo particolare motivo in Java 8. Il nome del metodo è tuttavia leggermente diverso.
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();
Mappe. Quando il numero di parametri è troppo grande e di solito vengono utilizzati per la maggior parte dei 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 = (Integer)parameters.get("a");
}
if (parameters.containsKey("b")) {
//...
}
//...
}
foo(ImmutableMap.<String, Object>of(
"a", "a",
"b", 2,
"d", "value"));
In Java 9, questo approccio è diventato più semplice:
@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"));
Si noti che è possibile combinare uno di questi approcci per ottenere un risultato desiderabile.
a
variabile è una stringa (il cast è corretto).
Esistono parametri opzionali con Java 5.0. Dichiara semplicemente la tua funzione in questo modo:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
potresti chiamare con doSomething();
o doSomething(true);
ora.
doSomething() { doSomething(true); }
, nessuna
Puoi usare qualcosa del genere:
public void addError(String path, String key, Object... params) {
}
La params
variabile è facoltativa Viene trattato come un array nullable di oggetti.
Stranamente, non ho trovato nulla al riguardo nella documentazione, ma funziona!
Questo è "nuovo" in Java 1.5 e versioni successive (non supportato in Java 1.4 o versioni precedenti).
Vedo anche l'utente bhoot menzionato di seguito.
Purtroppo Java non supporta direttamente i parametri predefiniti.
Tuttavia, ho scritto una serie di annotazioni JavaBean e una di esse supporta parametri predefiniti come il seguente:
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);
}
Il processore di annotazione genera i sovraccarichi del metodo per supportarlo correttamente.
Vedi http://code.google.com/p/javadude/wiki/Annotations
Esempio completo su http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample
Sono stati menzionati VarArgs e sovraccarico. Un'altra opzione è un modello Builder, che sarebbe simile a questo:
MyObject my = new MyObjectBuilder().setParam1(value)
.setParam3(otherValue)
.setParam6(thirdValue)
.build();
Sebbene quel modello sarebbe più appropriato per quando sono necessari parametri opzionali in un costruttore.
In JDK> 1.5 puoi usarlo in questo modo;
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);
}
}
}
Puoi fare qualcosa usando il metodo di sovraccarico in questo modo.
public void load(String name){ }
public void load(String name,int age){}
Inoltre puoi usare l'annotazione @Nullable
public void load(@Nullable String name,int age){}
passa semplicemente null come primo parametro.
Se stai passando la stessa variabile di tipo puoi usarla
public void load(String name...){}
Il sovraccarico va bene, ma se ci sono molte variabili che richiedono un valore predefinito, finirai con:
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) { }
Quindi suggerirei di usare l'argomento Variable fornito da Java. Ecco un link per la spiegazione.
Puoi usare una classe che funziona in modo molto simile a un builder per contenere i tuoi valori opzionali come questo.
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);
}
Usa come
foo(o -> o.setSomeString("something").setSomeInt(5));
L'output è
someString = something, someInt = 5
Per saltare tutti i valori opzionali che dovresti chiamarlo come foo(o -> {});
o se preferisci, puoi creare un secondo foo()
metodo che non accetta i parametri opzionali.
Utilizzando questo approccio, è possibile specificare valori opzionali in qualsiasi ordine senza alcuna ambiguità. Puoi anche avere parametri di classi diverse a differenza di varargs. Questo approccio sarebbe ancora migliore se fosse possibile utilizzare annotazioni e generazione di codice per creare la classe Options.
Java ora supporta gli opzionali in 1.8, sono bloccato con la programmazione su Android, quindi sto usando null fino a quando non posso refactoring il codice per utilizzare tipi opzionali.
Object canBeNull() {
if (blah) {
return new Object();
} else {
return null;
}
}
Object optionalObject = canBeNull();
if (optionalObject != null) {
// new object returned
} else {
// no new object returned
}
Gli argomenti predefiniti non possono essere utilizzati in Java. Dove in C #, C ++ e Python, possiamo usarli ..
In Java, dobbiamo usare 2 metodi (funzioni) anziché uno con parametri predefiniti.
Esempio:
Stash(int size);
Stash(int size, int initQuantity);
Questa è una vecchia domanda forse anche prima che fosse introdotto il tipo opzionale Opzionale, ma oggigiorno è possibile prendere in considerazione alcune cose: - utilizzare il metodo di overload - utilizzare il tipo Opzionale che ha il vantaggio di evitare il passaggio di NULL intorno al tipo Opzionale è stato introdotto in Java 8 prima che fosse normalmente usato da lib di terze parti come Guava di Google. L'uso facoltativo come parametri / argomenti può essere considerato un uso eccessivo poiché lo scopo principale era di usarlo come tempo di ritorno.
Rif: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html
Siamo in grado di impostare parametri opzionali sovraccaricando il metodo o utilizzando DataType ...
| * | Metodo di sovraccarico:
RetDataType NameFnc(int NamePsgVar)
{
// |* Code Todo *|
return RetVar;
}
RetDataType NameFnc(String NamePsgVar)
{
// |* Code Todo *|
return RetVar;
}
RetDataType NameFnc(int NamePsgVar1, String NamePsgVar2)
{
// |* Code Todo *|
return RetVar;
}
Il modo più semplice è
| * | DataType ... può essere un parametro opzionale
RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
if(stringOpnPsgVar.length == 0) stringOpnPsgVar = DefaultValue;
// |* Code Todo *|
return RetVar;
}
RetDtaTyp
... sul serio? È RetDataType
troppo difficile da scrivere?
Se si prevede di utilizzare un'interfaccia con più parametri , è possibile utilizzare il seguente modello strutturale e implementare o sostituire l'applicazione - un metodo basato sulle proprie esigenze .
public abstract class Invoker<T> {
public T apply() {
return apply(null);
}
public abstract T apply(Object... params);
}
Se si tratta di un endpoint API, un modo elegante è utilizzare le annotazioni "Spring":
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {
return innerFunc(id);
}
Si noti in questo caso che innerFunc richiederà la variabile e poiché non è un endpoint API, non è possibile utilizzare questa annotazione Spring per renderla facoltativa. Riferimento: https://www.baeldung.com/spring-request-param