O Java suporta valores de parâmetro padrão?

1661

Me deparei com algum código Java que tinha a seguinte estrutura:

public MyParameterizedFunction(String param1, int param2)
{
    this(param1, param2, false);
}

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
    //use all three parameters here
}

Eu sei que em C ++ posso atribuir um parâmetro a um valor padrão. Por exemplo:

void MyParameterizedFunction(String param1, int param2, bool param3=false);

O Java suporta esse tipo de sintaxe? Existem razões pelas quais essa sintaxe de duas etapas é preferível?

gnavi
fonte
85
Não. No entanto, o padrão Builder pode ajudar.
Dave Jarvis
50
Eu realmente sinto falta desse recurso. Isso ajuda muito ao modificar o código existente para tirar parâmetro extra para uma função ou construtor
Jatin
4
@Jatin Com a refatoração "Change method signature" do Eclipse, você pode adicionar um parâmetro e fornecer um valor padrão que os invocadores existentes usarão.
Erwin Bolwidt
2
@ErwinBolwidt Thanks. Estou usando o Android Studio e ele também tem a opção de refatorar o método e fornecer valores padrão. Bem útil.
Jatin
3
@temporary_user_name public MyParameterizedFunction(String param1, int param2)é uma declaração de construtor, não método.
Mario Ishac

Respostas:

955

Não, a estrutura que você encontrou é como o Java lida com isso (ou seja, com sobrecarga em vez de parâmetros padrão).

Para construtores, consulte Dica do Item 1 do Java Efetivo: Guia da Linguagem de Programação (Considere métodos estáticos de fábrica em vez de construtores) se a sobrecarga estiver ficando complicada. Para outros métodos, renomear alguns casos ou usar um objeto de parâmetro pode ajudar. É quando você tem complexidade suficiente que diferenciar é difícil. Um caso definido é onde você deve diferenciar usando a ordem dos parâmetros, não apenas o número e o tipo.

Kathy Van Stone
fonte
135
@JarrodRoberson: Os métodos estáticos de fábrica não são mais prejudiciais do que new. Eles são usados o tempo todo no novo código. Os construtores de objetos de valor simples geralmente são o resultado de excesso de engenharia.
Lii 22/01
12
@JarrodRoberson: Maneira interessante de forçar o uso correto através do compilador, obrigado por compartilhar! Sugestão amigável para futuras postagens: 300 linhas de código fonte não comentado provavelmente são um pouco demais para digerir para a maioria das pessoas (o código é mais difícil de ler do que escrever, afinal). Obrigado novamente!
Christian Aichinger
17
@JarrodRoberson: Legal, estou ansioso por isso! O que eu queria comunicar: como leitor do seu blog, um exemplo de 50 linhas com uma breve descrição do que está acontecendo me ajudaria a mais de 300 linhas sem contexto.
Christian Aichinger
8
@ user177800 Discordo - métodos estáticos se escritos como funções puras são perfeitamente adequados. É quando um estado se transforma função estática que eles se tornem um problema ...
Levi Fuller
642

Não, mas você pode usar o Padrão do Construtor , conforme descrito nesta resposta do estouro de pilha .

Conforme descrito na resposta vinculada, o Builder Pattern permite escrever código como

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

em que alguns campos podem ter valores padrão ou serem opcionais.

Eli Courtwright
fonte
142
Finalmente, um ótimo exemplo de menos de 2 páginas do padrão Builder.
N
14
Estou curioso, porém, por que precisamos de uma classe de construtor ao usar o padrão do construtor. Eu estava pensando em Student s1 = new Student () nome ( "Spicolo") idade (16) .motto ( "Aloha, Sr. Mão);..
ivanceras
52
@ivanceras: é relevante quando as classes têm campos obrigatórios e você não deseja instanciar essas classes em um estado inválido. Então, se você acabou de dizer Student s1 = new Student().age(16);, isso deixaria você com um aluno sem nome, o que pode ser ruim. Se não estiver ruim, sua solução está correta.
Eli Courtwright
57
@ivanceras: outro motivo é que você pode querer que sua classe seja imutável após a construção, para que você não queira métodos que alterem seus valores.
Jules
3
@ivanceras: Eu usei Builders para três coisas - eliminando o argumento múltiplo e a inicialização fluente, a imutabilidade e, o mais importante, para validar o objeto de domínio no método build (). Por que criar uma instância de objeto se for inválida? métodos de fábrica como no caso acima buildFreshman (), buildSenior () etc
Abhijeet Kushe
485

Existem várias maneiras de simular parâmetros padrão em Java:

  1. 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.

  2. 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.

  3. Nulos. Para abordar as limitações das abordagens anteriores, você pode permitir valores nulos e, em seguida, 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.

  4. 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.

  5. 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();
  6. Maps. Quando o número de parâmetros é muito grande e, para a maioria deles, os 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 = (String)parameters.get("a");
        } else if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 

Observe que você pode combinar qualquer uma dessas abordagens para obter um resultado desejável.

Vitalii Fedorenko
fonte
1
Boa explicação. Eu nunca vi valores de retorno usados ​​assim. Para 5) o que return thisfazer? Além disso, uma FooBuilder().setA("a").build();vez que (por definição) o construtor é chamado primeiro e FooBuilder()retorna um valor, isso não significa .setA("a"):que não tem a chance de ser chamado?
Celeritas
3
@Celeritas return thisretorna o mesmo objeto no qual o método foi chamado (no exemplo FooBuilder). Isso permite o encadeamento de métodos em uma instrução que atua no mesmo objeto: new FooBuilder().setA(..).setB(..).setC(..)etc, em vez de chamar cada método em uma instrução separada.
ADTC 27/08/14
2
@Celeritas new FooBuilder()retorna um FooBuilderobjeto no qual o setAmétodo é chamado. Como setBnão é chamado, this.bmantém o valor padrão. Finalmente, o buildmétodo é chamado nesse FooBuilderobjeto. O buildmétodo cria e retorna um Fooobjeto que está definido para a variável Foo foo. Observe que o FooBuilderobjeto não está armazenado em nenhuma variável.
ADTC 27/08/14
A anotação também pode ser usada para criar parâmetros padrão e é mais útil quando necessário para coleções polimórficas. docs.oracle.com/javase/tutorial/java/annotations/declaring.html
Martin Spamer
1
Mais de 900 votos positivos na mesma resposta em duas perguntas. Estou impressionado: stackoverflow.com/questions/965690/java-optional-parameters/...
AdamMc331
256

Infelizmente não.

Rob H
fonte
34
Isso é tão triste? Fazer isso introduziria assinaturas de função potencialmente ambíguas.
Trey
69
@Trey: idiomas com parâmetros padrão muitas vezes eliminam a sobrecarga de funções, pois são menos atraentes. Portanto, sem ambiguidade. Além disso, Scala adicionou o recurso na 2.8 e, de alguma forma, resolveu o problema de ambiguidade (já que eles mantinham a sobrecarga por motivos de compatibilidade).
PhiLho 24/05
32
Não vejo como os padrões impedem a sobrecarga de função. C #, por exemplo, permite substituições e também permite inicializações padrão. Parece escolha arbitrária, não restrição é o motivo.
FlavorScape
51
Sim, vamos compensar fazendo o compilador fazer um trabalho extra e, em vez disso, todos nós escrevemos 100000 sobrecargas para oferecer conveniência aos usuários de nossa biblioteca. Boa ideia.
28
@ user562566: Sempre que eu trabalhar em um projeto Java, fico com a impressão de que devs Java são pagos / medido pelo número de linhas de código que produzem por dia
Mark K Cowan
83

Infelizmente sim.

void MyParameterizedFunction(String param1, int param2, bool param3=false) {}

pode ser escrito em Java 1.5 como:

void MyParameterizedFunction(String param1, int param2, Boolean... params) {
    assert params.length <= 1;
    bool param3 = params.length > 0 ? params[0].booleanValue() : false;
}

Mas se você deve ou não depender de como se sente sobre o compilador gerar um

new Boolean[]{}

para cada chamada.

Para vários parâmetros padrão:

void MyParameterizedFunction(String param1, int param2, bool param3=false, int param4=42) {}

pode ser escrito em Java 1.5 como:

void MyParameterizedFunction(String param1, int param2, Object... p) {
    int l = p.length;
    assert l <= 2;
    assert l < 1 || Boolean.class.isInstance(p[0]);
    assert l < 2 || Integer.class.isInstance(p[1]);
    bool param3 = l > 0 && p[0] != null ? ((Boolean)p[0]).booleanValue() : false;
    int param4 = l > 1 && p[1] != null ? ((Integer)p[1]).intValue() : 42;
}

Isso corresponde à sintaxe do C ++, que permite apenas parâmetros padrão no final da lista de parâmetros.

Além da sintaxe, há uma diferença em que isso verifica o tipo de tempo de execução para parâmetros padrão passados ​​e o tipo C ++ os verifica durante a compilação.

ebelisle
fonte
14
Inteligente, mas varargs (...) só podem ser usados ​​para o parâmetro final, o que é mais limitador do que os idiomas suportados pelos parâmetros padrão.
CurtainDog
6
que é inteligente, mas um pouco confuso em relação a versão do C ++
alguém em algum lugar
5
Definitivamente, o Java precisa de parâmetros padrão opcionais, como C # e outros permitem ... a sintaxe é óbvia e presumo que eles possam implementar isso de maneira bastante simples, mesmo compilando todas as combinações possíveis ... Não consigo imaginar por que eles não o adicionaram à linguagem ainda!
jwl
10
Nunca se deve usar um assertcódigo em produção. Lance uma exceção.
Michael Dorst
5
-1 Não é para isso que servem os varargs. Isso é um truque. - neste caso, o uso de sobrecargas será muito mais legível (o que é lamentável, pois três caracteres extras são mais legíveis do que 5 linhas extras de origem ...). - mas o Java não suporta parâmetros padrão.
precisa saber é o seguinte
38

Não, mas você pode facilmente imitá-los. O que em C ++ foi:

public: void myFunction(int a, int b=5, string c="test") { ... }

Em Java, será uma função sobrecarregada:

public void myFunction(int a, int b, string c) { ... }

public void myFunction(int a, int b) {
    myFunction(a, b, "test");
}

public void myFunction(int a) {
    myFunction(a, 5);
}

Mencionado anteriormente, os parâmetros padrão causaram casos ambíguos na sobrecarga de funções. Isso simplesmente não é verdade, podemos ver no caso do C ++: sim, talvez ele possa criar casos ambíguos, mas esses problemas podem ser facilmente tratados. Simplesmente não foi desenvolvido em Java, provavelmente porque os criadores queriam uma linguagem muito mais simples como o C ++ - se eles tivessem razão, é outra questão. Mas a maioria de nós não acha que ele usa Java devido à sua simplicidade.

peterh - Restabelecer Monica
fonte
8
A idéia principal da notação de valor padrão do C # é precisamente evitar essa codificação padrão e ter apenas um construtor em vez de muitos.
Kolya Ivankov
1
@KolyaIvankov Não sei C #, mas sei C ++ onde o raciocínio é o mesmo. Eu não sei o que é melhor, mas acho que, na verdade, o mesmo código padrão é gerado pelo compilador no caso de C ++ / C # e está indo para o binário final.
peterh - Restabelece Monica
5
Toda linguagem de programação é (em particular) um meio de evitar um clichê do Assembler, estou errado? A questão é apenas se ela fornece uma funcionalidade útil ou não.
Kolya Ivankov
2
A primeira frase é uma pergunta retórica. A palavra "pergunta" na segunda frase não tem nada a ver com a pergunta retórica da primeira.
precisa
1
Sendo mais específico: as linguagens são ferramentas que permitem escrever programas de uma maneira que possamos ter controle sobre o que está escrito, compilar é uma maneira de dizer à máquina o que queremos dela. Uma ferramenta é mais útil se nos permite evitar clichês. Na verdade, o gnavi perguntou se eles podem evitar com precisão o tipo de código padrão que você propõe como resposta, já que o C # permite isso.
precisa
24

Você pode fazer isso no Scala, que é executado na JVM e é compatível com os programas Java. http://www.scala-lang.org/

ie

class Foo(var prime: Boolean = false, val rib: String)  {}
lítico
fonte
58
Trazer um idioma totalmente novo para obter um recurso não tão comum?
Om-nom-nom
8
@ om-nom-nom: Java nunca deveria existir. Dizer que um recurso não é usado equivale a que ninguém precisa dizer que o Java não era popular antes de ser inventado significa que Gosling não deveria começar a projetá-lo.
Val
28
@Val apenas dizendo que este é como atirar pássaros com seus canhões
om-nom-nom
8
que não tem nada a ver com a pergunta do OP
destan
Também trabalha em Kotlin. E Groovy. E C#. E Javascript. E quase todas as outras línguas criadas para pessoas e problemas reais.
spyro 29/04
17

Não , mas a maneira mais simples de implementar isso é:

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    param3 = param3 == null ? false : param3;
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

ou em vez do operador ternário , você pode usar if:

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    if (param3 == null) {
        param3 = false;
    }
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}
simhumileco
fonte
2
Sim, essa abordagem parece ser a melhor das outras alternativas. Ainda assim, seria bom para Java adotar valores padrão; Kotlin mostrou que isso pode ser feito, por isso não sei por que o Oracle não entra na era moderna e continua projetando java como se fosse a década de 1990. : D
shevy
13

Eu posso estar afirmando o óbvio aqui, mas por que não simplesmente implementar você mesmo o parâmetro "padrão"?

public class Foo() {
        public void func(String s){
                func(s, true);
        }
        public void func(String s, boolean b){
                //your code here
        }
}

para o padrão, você usaria

func("my string");

e se você não gostaria de usar o padrão, usaria

func("my string", false);
IronWolf
fonte
11
O pôster perguntou se esse padrão (bastante feio) pode ser evitado ... ;-) Em idiomas mais modernos (como c #, Scala), você não precisa dessas sobrecargas extras, que apenas criam mais linhas de código. Até certo ponto, você pode usar varargs enquanto isso (static int max (int ... array) {}), mas eles são apenas uma solução alternativa muito feia.
Offler
2
A sobrecarga não é feia e tem muitos benefícios, como chamadas de método diferentes com assinaturas diferentes podem executar funcionalidades diferentes. //This is better public class Foo() { /* This does something */ public void func(String s){ //do something } /* This does something else with b */ public void func(String s, boolean b){ // b was passed } } //Than this public class Foo() { /* This does something unless b = value, then it does something else */ public void func(String s, boolean b = value){ If (b){ // Do Something } else{ // Do something else } } }
Tony Booth
Bem, se alguém quer um comportamento diferente. Se a única diferença é uma pequena alteração nos cálculos, etc., é certo um desperdício de esforço criar várias assinaturas. Os padrões fazem sentido para onde você precisa ... e a falta dele não deve ser classificada como um requisito "inútil".
Kapil
Os parâmetros padrão do @Offler não têm nada a ver com "linguagem moderna". Eu os usei em Delphi há 20 anos e eles provavelmente já existiam no Turbo Pascal.
A incrível Jan
Eu concordo com Offler e discordo de Antony Booth. Acho isso não apenas feio, mas também bastante ineficiente. Idiomas como ruby ​​ou python tornam trivial o uso de parâmetros padrão; Eu acho que o Java exige que você faça é encontrar (e usar) soluções alternativas. A verificação explícita versus nula parece ser a opção menos feia, já que posso chamar isso também da linha de comando (apenas não forneça nada e depois lide com a variante sã); a abordagem de sobrecarga do operador parece ... muito detalhada (como pelo menos +3 linhas, em comparação com a verificação nula, e mais linhas se o código for mais complexo).
shevy
8

Como Scala foi mencionado, Kotlin também merece ser mencionado. Na função Kotlin, os parâmetros também podem ter valores padrão e podem até se referir a outros parâmetros:

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
    ...
}

Como o Scala, o Kotlin é executado na JVM e pode ser facilmente integrado aos projetos Java existentes.

Mrts
fonte
6

Não.

Você pode obter o mesmo comportamento passando um objeto com padrões inteligentes. Mas, novamente, depende de qual é o seu caso.

Santosh Gokak
fonte
5

Não. Em geral, o Java não possui muito (nenhum) açúcar sintático, pois eles tentaram criar uma linguagem simples.

tomjen
fonte
26
Não é bem assim. A verdade amarga é que a equipe estava em um cronograma apertado e não tinha tempo para açúcar sintático. Por que mais conste gotoser reservado palavras-chave que nenhuma implementação? - Especialmente consté algo que sinto muita falta - finalnão é substituto e eles sabiam disso. - E se você tomou a decisão consciente de nunca implementar goto, não precisará reservar a palavra-chave. - E mais tarde na equipe do Java, trapaceou, tornando o Label baseado breake continuetão poderoso quanto um Pascal goto.
Martin Martin
"Simples e Familiar Orientado a Objetos" era de fato um objetivo do projeto - ver oracle.com/technetwork/java/intro-141325.html
mikera
1
tomjen disse: "Não. Em geral, o Java não possui muito (nenhum) açúcar sintático, pois tentou criar uma linguagem simples". Então, você está dizendo que a remoção de muitos recursos desnecessários do C ++ faz do Java uma linguagem simples e me diga por que o Java tem métodos variados? Por que possui varargs? Não é necessário se você pode simplesmente usar uma matriz de objetos, estou certo? Portanto, os varargs podem ser removidos do idioma, porque é desnecessário. Isso tornará o Java mais simples do que é agora. Estou certo? A sobrecarga também pode ser removida, porque você tem nomes infinitos para cada método.
1
e é por isso que nós fomos primavera e outras coisas que levam a linguagem simples e transformar qualquer projeto de Java real para um clusterfuck de sintaxe e clichê :-)
matanster
Forçar desenvolvedores a elaborar códigos padronizados e soluções alternativas complicadas não é meu entendimento da palavra "fácil". myFunction (a, b = false, c = 3), é o que chamo de fácil.
spyro
5

Ao invés de usar:

void parameterizedMethod(String param1, int param2) {
    this(param1, param2, false);
}

void parameterizedMethod(String param1, int param2, boolean param3) {
    //use all three parameters here
}

Você pode utilizar a funcionalidade opcional do java tendo um único método:

void parameterizedMethod(String param1, int param2, @Nullable Boolean param3) {
    param3 = Optional.ofNullable(param3).orElse(false);
    //use all three parameters here
}

A principal diferença é que você deve usar classes de wrapper em vez de tipos Java primitivos para permitir nullentrada. Booleanem vez de boolean, em Integervez de inte assim por diante.

Viktor Taranenko
fonte
4

Não é suportado, mas existem várias opções, como o uso de padrão de objeto de parâmetro com algum açúcar de sintaxe:

public class Foo() {
    private static class ParameterObject {
        int param1 = 1;
        String param2 = "";
    }

    public static void main(String[] args) {
        new Foo().myMethod(new ParameterObject() {{ param1 = 10; param2 = "bar";}});
    }

    private void myMethod(ParameterObject po) {
    }
}

Nesta amostra, construímos ParameterObjectcom valores padrão e os substituímos na seção de inicialização da instância de classe{ param1 = 10; param2 = "bar";}

hoaz
fonte
3

Experimente esta solução:

public int getScore(int score, Integer... bonus)
{
    if(bonus.length > 0)
    {
        return score + bonus[0];
    }

    return score;
}
Hamzeh Soboh
fonte
3

Você pode usar o Java Method Invocation Builder para gerar automaticamente o construtor com valores padrão.

Basta adicionar @GenerateMethodInvocationBuilder à classe ou interface e o @Default aos parâmetros nos métodos em que você deseja valores padrão. Um construtor será gerado em tempo de compilação, usando os valores padrão que você especificou com suas anotações.

@GenerateMethodInvocationBuilder
public class CarService {
 public CarService() {
 }

 public String getCarsByFilter(//
   @Default("Color.BLUE") Color color, //
   @Default("new ProductionYear(2001)") ProductionYear productionYear,//
   @Default("Tomas") String owner//
 ) {
  return "Filtering... " + color + productionYear + owner;
 }
}

E então você pode invocar os métodos.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .invoke(instance);

Ou defina qualquer um dos valores padrão para outra coisa.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .withColor(Color.YELLOW)//
  .invoke(instance);
Tomas Bjerre
fonte
2

Uma abordagem semelhante a https://stackoverflow.com/a/13864910/2323964 que funciona no Java 8 é usar uma interface com getters padrão. Isso será mais amplo em branco, mas é ridículo, e é ótimo para quando você tem várias instâncias em que deseja chamar a atenção para os parâmetros.

public class Foo() {
    public interface Parameters {
        String getRequired();
        default int getOptionalInt(){ return 23; }
        default String getOptionalString(){ return "Skidoo"; }
    }

    public Foo(Parameters parameters){
        //...
    }

    public static void baz() {
        final Foo foo = new Foo(new Person() {
            @Override public String getRequired(){ return "blahblahblah"; }
            @Override public int getOptionalInt(){ return 43; }
        });
    }
}
Novaterata
fonte
2

Agora dediquei algum tempo para descobrir como usá-lo com métodos que retornam valores, e ainda não vi nenhum exemplo até agora, achei que seria útil adicionar isso aqui:

int foo(int a) {
    // do something with a
    return a;
}

int foo() {
    return foo(0); // here, 0 is a default value for a
}
AAGD
fonte
1

Foi assim que eu fiz ... não é tão conveniente, talvez, ter um 'argumento opcional' contra o seu parâmetro definido, mas ele faz o trabalho:

public void postUserMessage(String s,boolean wipeClean)
{
    if(wipeClean)
    {
        userInformation.setText(s + "\n");
    }
    else
    {
        postUserMessage(s);
    }
}

public void postUserMessage(String s)
{
    userInformation.appendText(s + "\n");
}

Observe que eu posso invocar o mesmo nome de método com apenas uma string ou com uma string e um valor booleano. Nesse caso, definir wipeClean como true substituirá todo o texto em minha TextArea pela string fornecida. Definir o wipeClean como false ou deixar de fora todos juntos simplesmente anexa o texto fornecido à TextArea.

Observe também que não estou repetindo o código nos dois métodos, apenas adicionando a funcionalidade de poder redefinir a TextArea criando um novo método com o mesmo nome apenas com o booleano adicionado.

Na verdade, acho que isso é um pouco mais limpo do que se o Java fornecesse um 'argumento opcional' para nossos parâmetros, já que precisaríamos codificar valores padrão etc. Nesse exemplo, não preciso me preocupar com nada disso. Sim, adicionei outro método à minha turma, mas é mais fácil ler a longo prazo na minha humilde opinião.

Michael Sims
fonte
1

NÃO, mas temos alternativas na forma de sobrecarga de função.

chamado quando nenhum parâmetro passou

void operation(){

int a = 0;
int b = 0;

} 

chamado quando "a" parâmetro foi passado

void operation(int a){

int b = 0;
//code

} 

chamado quando o parâmetro b passou

void operation(int a , int b){
//code
} 
Umair Khalid
fonte
1

Existem meia dúzia ou mais de problemas como esse; eventualmente, você chega ao padrão estático de fábrica ... veja a API de criptografia para isso. É difícil explicar, mas pense da seguinte maneira: se você tem um construtor, padrão ou não, a única maneira de propagar o estado além dos chavetas é ter um Boolean isValid; (junto com o valor nulo como padrão v com falha no construtor) ou lança uma exceção que nunca é informativa ao recuperá-la dos usuários de campo.

Código correto, caramba, escrevo milhares de construtores de linha e faço o que preciso. Acho que usando isValid na construção de objetos - em outras palavras, construtores de duas linhas - mas, por algum motivo, estou migrando para o padrão de fábrica estático. Parece que você pode fazer muito se estiver em uma chamada de método, ainda há problemas de sync (), mas os padrões podem ser 'substituídos' melhor (mais seguro)

Eu acho que o que precisamos fazer aqui é resolver a questão de nulo como valor padrão em relação a algo String one = new String (""); como uma variável membro, em seguida, verifique nulo antes de atribuir a sequência passada ao construtor.

Muito notável a quantidade de ciência da computação estratosférica bruta feita em Java.

C ++ e assim por diante tem bibliotecas de fornecedores, sim. O Java pode superá-los em servidores de grande escala devido à sua enorme caixa de ferramentas. Estude os blocos estáticos do inicializador, fique conosco.

Nicholas Jordan
fonte
1

Não é suportado em java como em outro idioma para ex. Kotlin.

Virendra Pal Singh
fonte
0

Você pode usar o seguinte-

public void mop(Integer x) {
  // Define default values
        x = x == null ? 200 : x;
}
Sobhit Sharma
fonte