Respostas:
varargs poderia fazer isso (de certa forma). Fora isso, todas as variáveis na declaração do método devem ser fornecidas. Se você deseja que uma variável seja opcional, você pode sobrecarregar o método usando uma assinatura que não exija o parâmetro
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
Existem várias maneiras de simular parâmetros opcionais em Java:
Sobrecarga de método.
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");
Uma das limitações dessa abordagem é que ela não funcionará se você tiver dois parâmetros opcionais do mesmo tipo e qualquer um deles puder ser omitido.
Varargs.
a) Todos os parâmetros opcionais são do mesmo 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) Os tipos de parâmetros opcionais podem 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");
A principal desvantagem dessa abordagem é que, se os parâmetros opcionais forem de tipos diferentes, você perderá a verificação de tipo estático. Além disso, se cada parâmetro tiver um significado diferente, você precisará de alguma maneira de distingui-lo.
Nulos. Para abordar as limitações das abordagens anteriores, você pode permitir valores nulos e analisar cada parâmetro em um corpo 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);
Agora todos os valores dos argumentos devem ser fornecidos, mas os padrão podem ser nulos.
Classe opcional. Essa abordagem é semelhante a nulos, mas usa a classe Java 8 Optional para parâmetros que possuem um valor padrão:
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 torna um contrato de método explícito para um chamador, no entanto, pode-se achar essa assinatura muito detalhada.
Atualização: o Java 8 inclui a classe java.util.Optional
pronta para uso, portanto, não há necessidade de usar a goiaba por esse motivo específico no Java 8. O nome do método é um pouco diferente.
Padrão do construtor. O padrão do construtor é usado para construtores e é implementado através da introdução de uma classe Builder 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();
Maps. Quando o número de parâmetros é muito grande e para a maioria dos valores padrão geralmente são usados, você pode passar argumentos de método como um mapa de seus nomes / 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"));
No Java 9, essa abordagem ficou mais 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"));
Observe que você pode combinar qualquer uma dessas abordagens para obter um resultado desejável.
a
variável seja uma String (a conversão está correta).
Existem parâmetros opcionais com o Java 5.0. Apenas declare sua função assim:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
você poderia ligar com doSomething();
ou doSomething(true);
agora.
doSomething() { doSomething(true); }
há matrizes para lidar com, nenhuma ambigüidade
Você pode usar algo como isto:
public void addError(String path, String key, Object... params) {
}
A params
variável é opcional. É tratado como uma matriz anulável de objetos.
Estranhamente, não consegui encontrar nada sobre isso na documentação, mas funciona!
Isso é "novo" no Java 1.5 e posterior (não suportado no Java 1.4 ou anterior).
Vejo que o usuário bhoot mencionou isso também abaixo.
Infelizmente, o Java não suporta parâmetros padrão diretamente.
No entanto, escrevi um conjunto de anotações JavaBean e uma delas suporta parâmetros padrão como o seguinte:
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);
}
O processador de anotação gera sobrecargas no método para dar suporte adequado a isso.
Consulte http://code.google.com/p/javadude/wiki/Annotations
Exemplo completo em http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample
VarArgs e sobrecarga foram mencionados. Outra opção é um padrão Builder, que seria algo como isto:
MyObject my = new MyObjectBuilder().setParam1(value)
.setParam3(otherValue)
.setParam6(thirdValue)
.build();
Embora esse padrão seja mais apropriado para quando você precisar de parâmetros opcionais em um construtor.
No JDK> 1.5, você pode usá-lo assim;
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);
}
}
}
Você pode fazer algo usando a sobrecarga de método como esta.
public void load(String name){ }
public void load(String name,int age){}
Além disso, você pode usar a anotação @Nullable
public void load(@Nullable String name,int age){}
simplesmente passe nulo como primeiro parâmetro.
Se você está passando a mesma variável de tipo, pode usar este
public void load(String name...){}
Sobrecarregar é bom, mas se houver muitas variáveis que precisam de valor padrão, você terá:
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) { }
Então, eu sugiro usar o argumento variável fornecido pelo Java. Aqui está um link para explicação.
Você pode usar uma classe que funciona como um construtor para conter seus valores opcionais 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);
}
Use como
foo(o -> o.setSomeString("something").setSomeInt(5));
Saída é
someString = something, someInt = 5
Para pular todos os valores opcionais que você teria que chamar assim foo(o -> {});
ou, se preferir, você pode criar um segundo foo()
método que não aceita os parâmetros opcionais.
Usando essa abordagem, você pode especificar valores opcionais em qualquer ordem sem ambiguidade. Você também pode ter parâmetros de diferentes classes, diferentemente dos varargs. Essa abordagem seria ainda melhor se você pudesse usar anotações e geração de código para criar a classe Options.
O Java agora suporta opcionais no 1.8. Estou preso à programação no Android, então estou usando nulos até que eu possa refatorar o código para usar tipos opcionais.
Object canBeNull() {
if (blah) {
return new Object();
} else {
return null;
}
}
Object optionalObject = canBeNull();
if (optionalObject != null) {
// new object returned
} else {
// no new object returned
}
Argumentos padrão não podem ser usados em Java. Onde em C #, C ++ e Python, podemos usá-los.
Em Java, precisamos usar 2 métodos (funções) em vez de um com parâmetros padrão.
Exemplo:
Stash(int size);
Stash(int size, int initQuantity);
Essa é uma pergunta antiga, talvez antes mesmo da introdução do tipo opcional real, mas hoje em dia você pode considerar algumas coisas: - sobrecarregar o método - usar o tipo opcional que tem a vantagem de evitar passar NULLs ao redor do tipo opcional que foi introduzido no Java 8 antes de ser normalmente usado de lib de terceiros, como o Guava do Google. O uso opcional de parâmetros / argumentos pode ser considerado um uso excessivo, pois o objetivo principal era usá-lo como um tempo de retorno.
Ref: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html
Podemos tornar o parâmetro opcional por Sobrecarga de método ou Usando DataType ...
| * | Sobrecarga de método:
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;
}
A maneira mais fácil é
| * | DataType ... pode ser parâmetro opcional
RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
if(stringOpnPsgVar.length == 0) stringOpnPsgVar = DefaultValue;
// |* Code Todo *|
return RetVar;
}
RetDtaTyp
... a sério? É RetDataType
muito difícil digitar?
Se você planeja usar uma interface com vários parâmetros , pode-se usar o seguinte padrão estrutural e implementar ou substituir aplicar - um método baseado em seus requisitos .
public abstract class Invoker<T> {
public T apply() {
return apply(null);
}
public abstract T apply(Object... params);
}
Se for um ponto de extremidade da API, uma maneira elegante é usar as anotações "Spring":
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {
return innerFunc(id);
}
Observe, nesse caso, que o innerFunc exigirá a variável e, como não é um ponto de extremidade da API, não pode usar esta anotação do Spring para torná-la opcional. Referência: https://www.baeldung.com/spring-request-param