Respuestas:
varargs podría hacer eso (de alguna manera). Aparte de eso, se deben proporcionar todas las variables en la declaración del método. Si desea que una variable sea opcional, puede sobrecargar el método utilizando una firma que no requiera el parámetro.
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
Hay varias formas de simular parámetros opcionales en Java:
Método de sobrecarga.
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 de las limitaciones de este enfoque es que no funciona si tiene dos parámetros opcionales del mismo tipo y cualquiera de ellos puede omitirse.
Varargs
a) Todos los parámetros opcionales son del mismo 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) Los tipos de parámetros opcionales pueden ser diferentes:
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");
El principal inconveniente de este enfoque es que si los parámetros opcionales son de diferentes tipos, pierde la comprobación de tipo estático. Además, si cada parámetro tiene un significado diferente, necesita alguna forma de distinguirlos.
Nulos Para abordar las limitaciones de los enfoques anteriores, puede permitir valores nulos y luego analizar cada parámetro en un cuerpo de método:
void foo(String a, Integer b, Integer c) {
b = b != null ? b : 0;
c = c != null ? c : 0;
//...
}
foo("a", null, 2);
Ahora se deben proporcionar todos los valores de argumentos, pero los valores predeterminados pueden ser nulos.
Clase opcional Este enfoque es similar a los nulos, pero usa la clase Java 8 Opcional para parámetros que tienen un valor predeterminado:
void foo(String a, Optional<Integer> bOpt) {
Integer b = bOpt.isPresent() ? bOpt.get() : 0;
//...
}
foo("a", Optional.of(2));
foo("a", Optional.<Integer>absent());
Opcional hace que un contrato de método sea explícito para una persona que llama, sin embargo, uno puede encontrar esa firma demasiado detallada.
Actualización: Java 8 incluye la clase lista java.util.Optional
para usar, por lo que no es necesario usar guayaba por esta razón particular en Java 8. Sin embargo, el nombre del método es un poco diferente.
Patrón de constructor. El patrón de constructor se utiliza para constructores y se implementa mediante la introducción de una clase de constructor separada:
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();
Mapas Cuando el número de parámetros es demasiado grande y para la mayoría de los valores predeterminados generalmente se usan, puede pasar argumentos de método como un mapa de sus nombres / valores:
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, este enfoque se hizo más fácil:
@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"));
Tenga en cuenta que puede combinar cualquiera de estos enfoques para lograr un resultado deseable.
a
variable es una cadena (el reparto es correcto).
Hay parámetros opcionales con Java 5.0. Simplemente declara tu función así:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
puedes llamar con doSomething();
o doSomething(true);
ahora.
doSomething() { doSomething(true); }
sin matrices para tratar, sin ambigüedad)
Puedes usar algo como esto:
public void addError(String path, String key, Object... params) {
}
La params
variable es opcional. Se trata como una matriz de objetos anulables.
Curiosamente, no pude encontrar nada sobre esto en la documentación, ¡pero funciona!
Esto es "nuevo" en Java 1.5 y posteriores (no compatible con Java 1.4 o anterior).
Veo que el usuario bhoot menciona esto también a continuación.
Desafortunadamente, Java no admite parámetros predeterminados directamente.
Sin embargo, he escrito un conjunto de anotaciones JavaBean, y una de ellas admite parámetros predeterminados como los siguientes:
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);
}
El procesador de anotaciones genera las sobrecargas del método para soportar esto correctamente.
Ver http://code.google.com/p/javadude/wiki/Annotations
Ejemplo completo en http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample
VarArgs y sobrecarga se han mencionado. Otra opción es un patrón Builder, que se vería así:
MyObject my = new MyObjectBuilder().setParam1(value)
.setParam3(otherValue)
.setParam6(thirdValue)
.build();
Aunque ese patrón sería más apropiado para cuando necesita parámetros opcionales en un constructor.
En JDK> 1.5 puedes usarlo así;
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);
}
}
}
Puede hacer cosas usando la sobrecarga de métodos de esta manera.
public void load(String name){ }
public void load(String name,int age){}
También puedes usar la anotación @Nullable
public void load(@Nullable String name,int age){}
simplemente pase nulo como primer parámetro.
Si está pasando la misma variable de tipo, puede usar esto
public void load(String name...){}
La sobrecarga está bien, pero si hay muchas variables que necesitan un valor predeterminado, terminarás 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) { }
Por lo tanto, sugeriría utilizar el argumento variable proporcionado por Java. Aquí hay un enlace para la explicación.
Puede usar una clase que funcione de manera muy similar a un generador para contener sus valores opcionales como este.
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);
}
Usar como
foo(o -> o.setSomeString("something").setSomeInt(5));
La salida es
someString = something, someInt = 5
Para omitir todos los valores opcionales, debería llamarlo así foo(o -> {});
o, si lo prefiere, puede crear un segundo foo()
método que no tome los parámetros opcionales.
Con este enfoque, puede especificar valores opcionales en cualquier orden sin ninguna ambigüedad. También puede tener parámetros de diferentes clases a diferencia de varargs. Este enfoque sería aún mejor si puede usar anotaciones y generación de código para crear la clase Opciones.
Java ahora admite opciones en 1.8, estoy atascado con la programación en Android, así que estoy usando nulos hasta que pueda refactorizar el código para usar tipos opcionales.
Object canBeNull() {
if (blah) {
return new Object();
} else {
return null;
}
}
Object optionalObject = canBeNull();
if (optionalObject != null) {
// new object returned
} else {
// no new object returned
}
Los argumentos predeterminados no se pueden usar en Java. Donde en C #, C ++ y Python, podemos usarlos.
En Java, debemos usar 2 métodos (funciones) en lugar de uno con parámetros predeterminados.
Ejemplo:
Stash(int size);
Stash(int size, int initQuantity);
Esta es una pregunta antigua tal vez incluso antes de que se introdujera el tipo opcional real, pero en estos días puede considerar algunas cosas: - use la sobrecarga del método - use el tipo opcional que tiene la ventaja de evitar pasar NULLs alrededor del tipo opcional se introdujo en Java 8 antes de que generalmente se usara de librerías de terceros, como la guayaba de Google. El uso de opcional como parámetros / argumentos puede considerarse un uso excesivo ya que el propósito principal era usarlo como un tiempo de retorno.
Ref: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html
Podemos hacer parámetros opcionales por sobrecarga de métodos o usando DataType ...
| * | Método de sobrecarga:
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;
}
La forma más fácil es
| * | DataType ... puede ser un parámetro opcional
RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
if(stringOpnPsgVar.length == 0) stringOpnPsgVar = DefaultValue;
// |* Code Todo *|
return RetVar;
}
RetDtaTyp
... ¿seriamente? ¿Es RetDataType
demasiado difícil de escribir?
Si planea usar una interfaz con múltiples parámetros , uno puede usar el siguiente patrón estructural e implementar o anular la aplicación, un método basado en sus requisitos .
public abstract class Invoker<T> {
public T apply() {
return apply(null);
}
public abstract T apply(Object... params);
}
Si se trata de un punto final de API, una forma elegante es usar anotaciones "Spring":
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {
return innerFunc(id);
}
Observe en este caso que innerFunc requerirá la variable y, dado que no es un punto final de API, no puede usar esta anotación Spring para hacerlo opcional. Referencia: https://www.baeldung.com/spring-request-param