Antworten:
varargs könnte das (in gewisser Weise) tun. Ansonsten müssen alle Variablen in der Deklaration der Methode angegeben werden. Wenn eine Variable optional sein soll, können Sie die Methode mit einer Signatur überladen, für die der Parameter nicht erforderlich ist.
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
Es gibt verschiedene Möglichkeiten, optionale Parameter in Java zu simulieren:
Methodenüberladung.
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");
Eine der Einschränkungen dieses Ansatzes besteht darin, dass er nicht funktioniert, wenn Sie zwei optionale Parameter desselben Typs haben und jeder von ihnen weggelassen werden kann.
Varargs.
a) Alle optionalen Parameter sind vom gleichen Typ:
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) Die Arten der optionalen Parameter können unterschiedlich sein:
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");
Der Hauptnachteil dieses Ansatzes besteht darin, dass bei statischen Parametern unterschiedlicher Typen die statische Typprüfung verloren geht. Wenn jeder Parameter eine andere Bedeutung hat, müssen Sie ihn auf irgendeine Weise unterscheiden.
Nullen. Um die Einschränkungen der vorherigen Ansätze zu beseitigen, können Sie Nullwerte zulassen und dann jeden Parameter in einem Methodenkörper analysieren:
void foo(String a, Integer b, Integer c) {
b = b != null ? b : 0;
c = c != null ? c : 0;
//...
}
foo("a", null, 2);
Jetzt müssen alle Argumentwerte angegeben werden, die Standardwerte können jedoch null sein.
Optionale Klasse. Dieser Ansatz ähnelt Nullen, verwendet jedoch die optionale Klasse Java 8 für Parameter mit einem Standardwert:
void foo(String a, Optional<Integer> bOpt) {
Integer b = bOpt.isPresent() ? bOpt.get() : 0;
//...
}
foo("a", Optional.of(2));
foo("a", Optional.<Integer>absent());
Optional wird ein Methodenvertrag für einen Anrufer explizit festgelegt. Eine solche Signatur ist jedoch möglicherweise zu ausführlich.
Update: Java 8 enthält die sofort einsatzbereite Klasse java.util.Optional
, sodass in Java 8 aus diesem speziellen Grund keine Guave verwendet werden muss. Der Methodenname ist jedoch etwas anders.
Builder-Muster. Das Builder-Muster wird für Konstruktoren verwendet und durch Einführung einer separaten Builder-Klasse implementiert:
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();
Karten. Wenn die Anzahl der Parameter zu groß ist und für die meisten Standardwerte normalerweise verwendet wird, können Sie Methodenargumente als Zuordnung ihrer Namen / Werte übergeben:
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 wurde dieser Ansatz einfacher:
@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"));
Bitte beachten Sie, dass Sie jeden dieser Ansätze kombinieren können, um ein wünschenswertes Ergebnis zu erzielen.
a
Variable ein String ist (Cast ist korrekt).
Optional
als Parameter in einer der Optionen ist diese Antwort sehr gut.
In Java 5.0 gibt es optionale Parameter. Deklarieren Sie einfach Ihre Funktion wie folgt:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
Sie könnten mit doSomething();
oder doSomething(true);
jetzt anrufen .
doSomething() { doSomething(true); }
keine Arrays, keine Mehrdeutigkeit
Sie können so etwas verwenden:
public void addError(String path, String key, Object... params) {
}
Die params
Variable ist optional. Es wird als nullbares Array von Objekten behandelt.
Seltsamerweise konnte ich in der Dokumentation nichts dazu finden, aber es funktioniert!
Dies ist "neu" in Java 1.5 und höher (wird in Java 1.4 oder früher nicht unterstützt).
Ich sehe, dass Benutzer bhoot dies auch unten erwähnt hat.
Leider unterstützt Java Standardparameter nicht direkt.
Ich habe jedoch eine Reihe von JavaBean-Anmerkungen geschrieben, von denen eine Standardparameter wie die folgenden unterstützt:
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);
}
Der Anmerkungsprozessor generiert die Methodenüberladungen, um dies ordnungsgemäß zu unterstützen.
Siehe http://code.google.com/p/javadude/wiki/Annotations
Vollständiges Beispiel unter http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample
VarArgs und Überladung wurden erwähnt. Eine andere Option ist ein Builder-Muster, das ungefähr so aussehen würde:
MyObject my = new MyObjectBuilder().setParam1(value)
.setParam3(otherValue)
.setParam6(thirdValue)
.build();
Obwohl dieses Muster am besten geeignet ist, wenn Sie optionale Parameter in einem Konstruktor benötigen.
In JDK> 1.5 können Sie es so verwenden;
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);
}
}
}
Sie können dies mit einer solchen Methodenüberladung tun.
public void load(String name){ }
public void load(String name,int age){}
Sie können auch die Annullation @Nullable verwenden
public void load(@Nullable String name,int age){}
Übergeben Sie einfach null als ersten Parameter.
Wenn Sie dieselbe Typvariable übergeben, können Sie diese verwenden
public void load(String name...){}
Überladen ist in Ordnung, aber wenn es viele Variablen gibt, die einen Standardwert benötigen, erhalten Sie Folgendes:
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) { }
Daher würde ich vorschlagen, das von Java bereitgestellte Variablenargument zu verwenden. Hier ist ein Link zur Erklärung.
Sie können eine Klasse verwenden, die ähnlich wie ein Builder funktioniert, um Ihre optionalen Werte wie diese zu enthalten.
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);
}
Verwenden Sie wie
foo(o -> o.setSomeString("something").setSomeInt(5));
Ausgabe ist
someString = something, someInt = 5
Um alle optionalen Werte zu überspringen, die Sie wie folgt aufrufen foo(o -> {});
möchten, oder wenn Sie dies bevorzugen, können Sie eine zweite foo()
Methode erstellen , die die optionalen Parameter nicht verwendet.
Mit diesem Ansatz können Sie optionale Werte in beliebiger Reihenfolge ohne Mehrdeutigkeit angeben. Im Gegensatz zu varargs können Sie auch Parameter verschiedener Klassen verwenden. Dieser Ansatz wäre sogar noch besser, wenn Sie zum Erstellen der Options-Klasse Anmerkungen und Codegenerierung verwenden können.
Java unterstützt jetzt Optionals in 1.8. Ich bin mit der Programmierung auf Android festgefahren, daher verwende ich Nullen, bis ich den Code umgestalten kann, um optionale Typen zu verwenden.
Object canBeNull() {
if (blah) {
return new Object();
} else {
return null;
}
}
Object optionalObject = canBeNull();
if (optionalObject != null) {
// new object returned
} else {
// no new object returned
}
Standardargumente können in Java nicht verwendet werden. Wo in C #, C ++ und Python können wir sie verwenden.
In Java müssen wir 2 Methoden (Funktionen) anstelle einer mit Standardparametern verwenden.
Beispiel:
Stash(int size);
Stash(int size, int initQuantity);
Dies ist eine alte Frage, vielleicht noch bevor der eigentliche optionale Typ eingeführt wurde, aber heutzutage können Sie einige Dinge berücksichtigen: - Überladen von Methoden verwenden - Optionalen Typ verwenden, der den Vorteil hat, dass NULL-Werte nicht um den optionalen Typ herum übergeben werden, wurde in Java 8 eingeführt, bevor er normalerweise verwendet wurde von Drittanbietern wie Googles Guava. Die Verwendung von optional als Parameter / Argumente kann als Überbeanspruchung angesehen werden, da der Hauptzweck darin bestand, sie als Rückgabezeit zu verwenden.
Ref: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html
Wir können optionale Parameter durch Überladen von Methoden oder Verwenden von DataType festlegen ...
| * | Methodenüberladung:
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;
}
Der einfachste Weg ist
| * | DataType ... kann ein optionaler Parameter sein
RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
if(stringOpnPsgVar.length == 0) stringOpnPsgVar = DefaultValue;
// |* Code Todo *|
return RetVar;
}
RetDtaTyp
... Ernsthaft? Ist RetDataType
zu schwer zu tippen?
Wenn Sie eine Schnittstelle mit mehreren Parametern verwenden möchten , können Sie das folgende Strukturmuster verwenden und apply implementieren oder überschreiben - eine Methode, die auf Ihren Anforderungen basiert .
public abstract class Invoker<T> {
public T apply() {
return apply(null);
}
public abstract T apply(Object... params);
}
Wenn es sich um einen API-Endpunkt handelt, können Sie auf elegante Weise "Spring" -Anmerkungen verwenden:
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {
return innerFunc(id);
}
Beachten Sie in diesem Fall, dass für innerFunc die Variable erforderlich ist. Da es sich nicht um einen API-Endpunkt handelt, kann diese Spring-Annotation nicht verwendet werden, um sie optional zu machen. Referenz: https://www.baeldung.com/spring-request-param