Réponses:
varargs pourrait le faire (en quelque sorte). En dehors de cela, toutes les variables de la déclaration de la méthode doivent être fournies. Si vous voulez qu'une variable soit facultative, vous pouvez surcharger la méthode en utilisant une signature qui ne nécessite pas le paramètre.
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
Il existe plusieurs façons de simuler des paramètres facultatifs en Java:
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.
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.
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.
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.
Mise à jour: Java 8 inclut la classe java.util.Optional
prête à l'emploi, il n'est donc pas nécessaire d'utiliser la goyave pour cette raison particulière dans Java 8. Le nom de la méthode est cependant un peu différent.
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();
Plans. Lorsque le nombre de paramètres est trop grand et que la plupart des valeurs par défaut sont généralement utilisées, 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 = (Integer)parameters.get("a");
}
if (parameters.containsKey("b")) {
//...
}
//...
}
foo(ImmutableMap.<String, Object>of(
"a", "a",
"b", 2,
"d", "value"));
En Java 9, cette approche est devenue plus simple:
@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"));
Veuillez noter que vous pouvez combiner n'importe laquelle de ces approches pour obtenir un résultat souhaitable.
a
variable soit une chaîne (le cast est correct).
Il existe des paramètres facultatifs avec Java 5.0. Déclarez simplement votre fonction comme ceci:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
vous pouvez appeler avec doSomething();
ou doSomething(true);
maintenant.
doSomething() { doSomething(true); }
pas de tableaux à traiter, pas d'ambiguïté
Vous pouvez utiliser quelque chose comme ceci:
public void addError(String path, String key, Object... params) {
}
La params
variable est facultative. Il est traité comme un tableau d'objets nullable.
Étrangement, je n'ai rien trouvé à ce sujet dans la documentation, mais ça marche!
C'est "nouveau" dans Java 1.5 et au-delà (non pris en charge dans Java 1.4 ou version antérieure).
Je vois que l'utilisateur bhoot l'a mentionné aussi ci-dessous.
Malheureusement, Java ne prend pas directement en charge les paramètres par défaut.
Cependant, j'ai écrit un ensemble d'annotations JavaBean, et l'une d'entre elles prend en charge les paramètres par défaut comme les suivants:
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);
}
Le processeur d'annotation génère les surcharges de méthode pour prendre correctement en charge cela.
Voir http://code.google.com/p/javadude/wiki/Annotations
Exemple complet sur http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample
VarArgs et surcharge ont été mentionnés. Une autre option est un modèle Builder, qui ressemblerait à ceci:
MyObject my = new MyObjectBuilder().setParam1(value)
.setParam3(otherValue)
.setParam6(thirdValue)
.build();
Bien que ce modèle soit plus approprié lorsque vous avez besoin de paramètres facultatifs dans un constructeur.
Dans JDK> 1.5, vous pouvez l'utiliser comme ceci;
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);
}
}
}
Vous pouvez faire quelque chose en utilisant une surcharge de méthode comme celle-ci.
public void load(String name){ }
public void load(String name,int age){}
Vous pouvez également utiliser l'annotation @Nullable
public void load(@Nullable String name,int age){}
passez simplement null comme premier paramètre.
Si vous passez une variable de même type, vous pouvez utiliser ceci
public void load(String name...){}
La surcharge est très bien, mais s'il y a beaucoup de variables qui nécessitent une valeur par défaut, vous vous retrouverez avec:
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) { }
Je suggère donc d'utiliser l'argument variable fourni par Java. Voici un lien pour l'explication.
Vous pouvez utiliser une classe qui fonctionne un peu comme un générateur pour contenir vos valeurs facultatives comme celle-ci.
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);
}
Utilisez comme
foo(o -> o.setSomeString("something").setSomeInt(5));
La sortie est
someString = something, someInt = 5
Pour ignorer toutes les valeurs facultatives, vous devez l'appeler comme foo(o -> {});
ou si vous préférez, vous pouvez créer une deuxième foo()
méthode qui ne prend pas les paramètres facultatifs.
En utilisant cette approche, vous pouvez spécifier des valeurs facultatives dans n'importe quel ordre sans aucune ambiguïté. Vous pouvez également avoir des paramètres de différentes classes contrairement aux varargs. Cette approche serait encore meilleure si vous pouvez utiliser des annotations et la génération de code pour créer la classe Options.
Java prend désormais en charge les options dans la version 1.8, je suis coincé avec la programmation sur Android, donc j'utilise des valeurs nulles jusqu'à ce que je puisse refactoriser le code pour utiliser des types facultatifs.
Object canBeNull() {
if (blah) {
return new Object();
} else {
return null;
}
}
Object optionalObject = canBeNull();
if (optionalObject != null) {
// new object returned
} else {
// no new object returned
}
Les arguments par défaut ne peuvent pas être utilisés en Java. Où en C #, C ++ et Python, nous pouvons les utiliser.
En Java, nous devons utiliser 2 méthodes (fonctions) au lieu d'une avec des paramètres par défaut.
Exemple:
Stash(int size);
Stash(int size, int initQuantity);
C'est une vieille question peut-être même avant l'introduction du type facultatif réel, mais de nos jours, vous pouvez considérer quelques choses: - utiliser la surcharge de méthode - utiliser le type facultatif qui a l'avantage d'éviter de passer des NULL autour Le type facultatif a été introduit dans Java 8 avant qu'il ne soit généralement utilisé à partir d'une bibliothèque tierce telle que Google's Guava. L'utilisation de paramètres / arguments facultatifs peut être considérée comme une surutilisation car le but principal était de l'utiliser comme heure de retour.
Réf: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html
Nous pouvons faire des paramètres facultatifs par surcharge de méthode ou en utilisant DataType ...
| * | Surcharge de méthode:
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;
}
Le moyen le plus simple est
| * | DataType ... peut être un paramètre facultatif
RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
if(stringOpnPsgVar.length == 0) stringOpnPsgVar = DefaultValue;
// |* Code Todo *|
return RetVar;
}
RetDtaTyp
... sérieusement? Est-ce RetDataType
trop difficile à taper?
Si vous prévoyez d'utiliser une interface avec plusieurs paramètres , vous pouvez utiliser le modèle structurel suivant et implémenter ou remplacer apply - une méthode basée sur vos besoins .
public abstract class Invoker<T> {
public T apply() {
return apply(null);
}
public abstract T apply(Object... params);
}
S'il s'agit d'un point de terminaison API, une méthode élégante consiste à utiliser des annotations "Spring":
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {
return innerFunc(id);
}
Notez dans ce cas que le innerFunc aura besoin de la variable, et comme ce n'est pas un point de terminaison api, ne peut pas utiliser cette annotation Spring pour la rendre facultative. Référence: https://www.baeldung.com/spring-request-param