¿Java admite valores de parámetros predeterminados?

1661

Encontré un código Java que tenía la siguiente estructura:

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

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

Sé que en C ++ puedo asignar a un parámetro un valor predeterminado. Por ejemplo:

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

¿Java admite este tipo de sintaxis? ¿Hay alguna razón por la cual esta sintaxis de dos pasos es preferible?

gnavi
fuente
85
No. Sin embargo, el patrón Builder puede ayudar.
Dave Jarvis
50
Realmente extraño esta característica. Ayuda mucho al modificar el código existente para llevar parámetros adicionales a una función o constructor
Jatin
44
@Jatin Con la refactorización "Cambiar firma de método" de Eclipse, puede agregar un parámetro y proporcionar un valor predeterminado que utilizarán los invocadores existentes.
Erwin Bolwidt
2
@ErwinBolwidt Gracias. Estoy usando Android Studio, y también tiene la opción de refactorizar el método y proporcionar valores predeterminados. Bastante útil.
Jatin
3
@temporary_user_name public MyParameterizedFunction(String param1, int param2)es un constructor, no un método, una declaración.
Mario Ishac

Respuestas:

955

No, la estructura que encontró es cómo Java lo maneja (es decir, con sobrecarga en lugar de parámetros predeterminados).

Para los constructores, consulte Sugerencia del artículo 1 de Java eficaz: Guía del lenguaje de programación (considere métodos de fábrica estáticos en lugar de constructores) si la sobrecarga se complica. Para otros métodos, puede ser útil cambiar el nombre de algunos casos o usar un objeto de parámetro. Esto es cuando tienes suficiente complejidad que diferenciar es difícil. Un caso definitivo es donde debe diferenciarse utilizando el orden de los parámetros, no solo el número y el tipo.

Kathy Van Stone
fuente
135
@JarrodRoberson: los métodos de fábrica estáticos no son más dañinos que new. Se usan todo el tiempo en código nuevo. Los constructores de objetos de valor simple a menudo son el resultado de una ingeniería excesiva.
Lii
12
@JarrodRoberson: forma interesante de forzar el uso correcto a través del compilador, ¡gracias por compartir! Sugerencia amigable para publicaciones futuras: 300 líneas de código fuente no comentado es probablemente un poco difícil de digerir para la mayoría de las personas (después de todo, el código es más difícil de leer que de escribir). ¡Gracias de nuevo!
Christian Aichinger
17
@JarrodRoberson: ¡Qué bueno! Lo que quería comunicar: como lector de su blog, un ejemplo de 50 líneas con una breve descripción de texto de lo que está sucediendo me ayudaría a más de 300 líneas sin contexto.
Christian Aichinger
8
@ user177800 En desacuerdo: los métodos estáticos si se escriben como funciones puras están perfectamente bien. Es cuando una función estática muta indica que se convierten en un problema ...
Levi Fuller
642

No, pero puede usar el Patrón del generador , como se describe en esta respuesta de Desbordamiento de pila .

Como se describe en la respuesta vinculada, el Patrón del generador le permite escribir código como

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

en el que algunos campos pueden tener valores predeterminados o ser opcionales.

Eli Courtwright
fuente
142
Finalmente, un excelente ejemplo de menos de 2 páginas del patrón Builder.
nevvermind
14
Sin embargo, tengo curiosidad, ¿por qué necesitamos una clase de generador cuando usamos el patrón de generador? Estaba pensando en Student s1 = new Student (). Name ("Spicolo"). Age (16) .motto ("Aloha, Mr Hand);
ivanceras
52
@ivanceras: es relevante cuando las clases tienen campos obligatorios, y no desea poder instanciar esas clases en un estado no válido. Entonces, si acabas de decirlo Student s1 = new Student().age(16);, eso te dejaría con un Estudiante sin nombre, lo que podría ser malo. Si no está mal, entonces su solución está bien.
Eli Courtwright
57
@ivanceras: otra razón es que es posible que desee que su clase sea inmutable después de la construcción, por lo que no querría métodos que cambien sus valores.
Julio
3
@ivanceras: utilicé Builders para 3 cosas: eliminar el argumento múltiple y la inicialización fluida, la inmutabilidad y, lo que es más importante, creo que validar el objeto de dominio en el método build (). Por qué crear una instancia de objeto si no es válida. métodos de fábrica como en el caso anterior buildFreshman (), buildSenior (), etc.
Abhijeet Kushe
485

Hay varias formas de simular parámetros predeterminados en Java:

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

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

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

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

  5. 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();
  6. Mapas Cuando el número de parámetros es demasiado grande y para la mayoría de ellos se usan valores predeterminados, 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 = (String)parameters.get("a");
        } else if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 

Tenga en cuenta que puede combinar cualquiera de estos enfoques para lograr un resultado deseable.

Vitalii Fedorenko
fuente
1
Buena explicación. Nunca he visto valores de retorno utilizados de esta manera. Para 5) ¿qué return thishacer? Además, FooBuilder().setA("a").build();desde entonces (por definición) el constructor se llama primero y FooBuilder()devuelve un valor, ¿no significa esto .setA("a"):que no tiene la oportunidad de ser llamado?
Celeritas
3
@Celeritas return thisdevuelve el mismo objeto en el que se llamó al método (en el ejemplo, FooBuilder). Esto permite el encadenamiento de métodos en una declaración que actúa sobre el mismo objeto: new FooBuilder().setA(..).setB(..).setC(..)etc. en lugar de llamar a cada método en una declaración separada.
ADTC
2
@Celeritas new FooBuilder()devuelve un FooBuilderobjeto en el que setAse llama al método. Como setBno se llama, this.bconserva el valor predeterminado. Finalmente buildse llama al método en este FooBuilderobjeto. El buildmétodo crea y devuelve un Fooobjeto que se establece en la variable Foo foo. Tenga en cuenta que el FooBuilderobjeto no está almacenado en ninguna variable.
ADTC
La anotación también se puede usar para crear parámetros predeterminados y es más útil cuando se requiere para colecciones polimórficas. docs.oracle.com/javase/tutorial/java/annotations/declaring.html
Martin Spamer
1
Más de 900 votos a favor en la misma respuesta en dos preguntas. Estoy impresionado: stackoverflow.com/questions/965690/java-optional-parameters/…
AdamMc331
256

Tristemente no.

Rob H
fuente
34
¿Es tan triste? Hacerlo introduciría firmas de funciones potencialmente ambiguas.
Trey
69
@Trey: los idiomas con parámetros predeterminados suelen deshacerse de la sobrecarga de funciones, ya que es menos convincente. Entonces no hay ambigüedad. Además, Scala agregó la función en 2.8 y de alguna manera resolvió el problema de la ambigüedad (ya que mantuvieron la sobrecarga por razones de compatibilidad).
PhiLho
32
No veo cómo los valores predeterminados de los parámetros evitan la sobrecarga de la función. C #, por ejemplo, permite anulaciones y también permite inicializaciones predeterminadas. Parece una elección arbitraria, no restricción es la razón.
FlavorScape
51
Sí, cambiemos haciendo que el compilador haga un trabajo extra y, en cambio, hagamos que todos escribamos 100000 sobrecargas para brindar comodidad a los usuarios de nuestra biblioteca. Buena idea.
28
@ user562566: Cada vez que trabajo en un proyecto Java, tengo la impresión de que los desarrolladores de Java son pagados / medidos por la cantidad de líneas de código que producen por día
Mark K Cowan
83

Por desgracia sí.

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

podría escribirse en 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;
}

Pero si debe o no depender de cómo se siente acerca del compilador que genera un

new Boolean[]{}

para cada llamada

Para múltiples parámetros predeterminados:

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

podría escribirse en 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;
}

Esto coincide con la sintaxis de C ++, que solo permite parámetros predeterminados al final de la lista de parámetros.

Más allá de la sintaxis, existe una diferencia en la que esto ha llevado a cabo la comprobación del tipo de tiempo para los parámetros predeterminados pasados ​​y el tipo C ++ los verifica durante la compilación.

ebelisle
fuente
14
Inteligente, pero los varargs (...) solo se pueden usar para el parámetro final, lo que es más limitante que los idiomas que admiten los parámetros predeterminados.
CurtainDog
66
eso es inteligente pero un poco desordenado en comparación con la versión C ++
Someone Somewhere
55
Java definitivamente necesita parámetros predeterminados opcionales, ya que C # y otros lo permiten ... la sintaxis es obvia y supongo que pueden implementar esto de manera bastante simple, incluso simplemente compilando todas las combinaciones posibles ... No puedo imaginar por qué no lo han agregado al lenguaje ¡todavía!
jwl
10
Uno nunca debe usar un assertcódigo en producción. Lanza una excepción.
Michael Dorst
55
-1 Esto realmente no es para lo que varargs es. Este es un truco. - en este caso, usar sobrecargas será mucho más legible (lo cual es desafortunado, ya que tres caracteres adicionales son más legibles que 5 líneas adicionales de fuente ...). - pero Java no admite parámetros predeterminados.
BrainSlugs83
38

No, pero puedes emularlos muy fácilmente. Lo que en C ++ fue:

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

En Java, será una función sobrecargada:

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);
}

Anteriormente se mencionó que los parámetros predeterminados causaron casos ambiguos en la sobrecarga de funciones. Eso simplemente no es cierto, podemos ver en el caso de C ++: sí, tal vez pueda crear casos ambiguos, pero estos problemas pueden manejarse fácilmente. Simplemente no se desarrolló en Java, probablemente porque los creadores querían un lenguaje mucho más simple como lo era C ++; si tenían razón, es otra pregunta. Pero la mayoría de nosotros no cree que use Java debido a su simplicidad.

peterh - Restablece a Monica
fuente
8
La idea principal de la notación de valor predeterminado de C # es precisamente evitar esta codificación repetitiva y tener solo un constructor en lugar de muchos.
Kolya Ivankov
1
@ KolyaIvankov No sé C #, pero sé C ++ donde el razonamiento es el mismo. No sé qué es lo mejor, pero creo que, en realidad, el compilador genera el mismo código repetitivo en el caso de C ++ / C # y va al binario final.
peterh - Restablece a Monica el
55
Cada lenguaje de programación es (en particular) un medio para evitar una repetitiva de ensamblador, ¿me equivoco? La pregunta es solo si ofrece una funcionalidad práctica o no.
Kolya Ivankov
2
La primera oración es una pregunta retórica. La palabra "pregunta" en la segunda oración no tiene nada que ver con la pregunta retórica en la primera.
Kolya Ivankov
1
Siendo más específico: los lenguajes son herramientas que nos permiten escribir programas de manera que podamos tener control sobre lo que está escrito, compilar es una forma de decirle a una máquina lo que queremos de él. Una herramienta es más útil si nos permite evitar repeticiones. En efecto, preguntó gnavi, si pueden evitar con precisión el tipo de código repetitivo que propone como respuesta, ya que C # lo permite.
Kolya Ivankov
24

Puede hacerlo en Scala, que se ejecuta en la JVM y es compatible con los programas Java. http://www.scala-lang.org/

es decir

class Foo(var prime: Boolean = false, val rib: String)  {}
lítico
fuente
58
¿Trae un lenguaje completamente nuevo para obtener una característica no tan común?
om-nom-nom
8
@ om-nom-nom: Java nunca debería existir. Decir que una característica no se usa es equivalente a que nadie la necesita, decir que Java no era popular antes de que se inventara significa que Gosling no debería comenzar a diseñarla.
Val
28
@Val solo dice que esto es como disparar pájaros con cañones
om-nom-nom
8
eso no tiene nada que ver con la pregunta del OP
destan
También funciona en Kotlin. Y Groovy. Y C#. Y Javascript. Y casi todos los demás idiomas que están hechos para personas reales y problemas.
Spyro
17

No , pero la forma más sencilla de implementar esto es:

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

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

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

o en lugar del operador ternario , puede 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
fuente
2
Sí, este enfoque parece ser el mejor de las otras alternativas. Aún así, sería bueno para Java adoptar valores predeterminados; Kotlin demostró que esto se puede hacer, por lo que no estoy seguro de por qué Oracle no ingresa a la era moderna y sigue diseñando Java como si fuera la década de 1990. : D
shevy
13

Podría estar diciendo lo obvio aquí, pero ¿por qué no simplemente implementar el parámetro "predeterminado" usted mismo?

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

por defecto, usted usaría

func("my string");

y si no desea usar el predeterminado, usaría

func("my string", false);
IronWolf
fuente
11
El póster preguntó si este patrón (bastante feo) se puede evitar ... ;-) En lenguajes más modernos (como c #, Scala) no necesita estas sobrecargas adicionales que solo crean más líneas de código. Mientras tanto, puede usar varargs mientras tanto (static int max (int ... array) {}), pero son solo una solución muy fea.
Offler
2
La sobrecarga no es fea y tiene muchos beneficios, como diferentes llamadas a métodos con diferentes firmas que pueden realizar diferentes funciones. //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 } } }
Antony Booth
Bueno, si uno quiere un comportamiento diferente. Si la única diferencia es un ligero cambio en los cálculos, etc., es una pérdida de esfuerzo crear múltiples firmas. Los valores predeterminados tienen sentido donde los necesita ... y su falta no debe clasificarse como un requisito "inútil".
Kapil
Los parámetros predeterminados de @Offler no tienen nada que ver con el "lenguaje moderno". Los usé en Delphi hace 20 años y probablemente ya existían en Turbo Pascal.
El increíble Jan
Estoy de acuerdo con Offler y no estoy de acuerdo con Antony Booth. Lo encuentro no solo feo sino también bastante ineficiente. Los lenguajes como ruby ​​o python hacen que sea trivial usar parámetros predeterminados; Supongo que lo que Java requiere que hagas es encontrar (y usar) soluciones alternativas. La verificación explícita versus nulo parece ser la opción menos fea, ya que también puedo llamarlo desde la línea de comandos (simplemente no proporcionar nada, y luego manejar la variante sensata); el enfoque de sobrecarga del operador parece ... muy detallado (como al menos +3 líneas, en comparación con la verificación nula, y más líneas si el código es más complejo).
shevy
8

Como se mencionó a Scala, Kotlin también vale la pena mencionar. En la función Kotlin, los parámetros también pueden tener valores predeterminados e incluso pueden referirse a otros parámetros:

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

Al igual que Scala, Kotlin se ejecuta en la JVM y puede integrarse fácilmente en proyectos Java existentes.

mrts
fuente
6

No.

Puede lograr el mismo comportamiento al pasar un objeto que tiene valores predeterminados inteligentes. Pero, de nuevo, depende de cuál sea su caso.

Santosh Gokak
fuente
5

No. En general, Java no tiene mucho (ningún) azúcar sintáctico, ya que intentaron crear un lenguaje simple.

tomjen
fuente
26
No exactamente. La amarga verdad es que el equipo tenía un horario apretado y no tenía tiempo para el azúcar sintáctico. ¿Por qué otra razón serían consty gotoserían palabras clave reservadas sin implementación? - Especialmente constes algo que extraño mucho - finalno es un reemplazo y ellos lo sabían. - Y si tomó la decisión consciente de no implementar nunca goto, no tendrá que reservar la palabra clave. - Y más tarde en el Equipo Java engañó haciendo que la Etiqueta se basara breaky fuera continuetan poderosa como un Pascal goto.
Martin
"Simple, orientado a objetos y familiar" fue, de hecho, un objetivo de diseño - vea oracle.com/technetwork/java/intro-141325.html
mikera
1
tomjen dijo: "No. En general, Java no tiene mucho (ningún) azúcar sintáctico, ya que intentaron hacer un lenguaje simple". Entonces, ¿estás diciendo que eliminar muchas características innecesarias de C ++ hace que Java sea un lenguaje simple, luego dime por qué Java tiene métodos variables? ¿Por qué tiene varargs? No es necesario si simplemente puedes usar una matriz de objetos, ¿estoy en lo cierto? Por lo tanto, los varargs se pueden eliminar del idioma, porque es innecesario. Esto hará que Java sea más simple de lo que es ahora. Estoy en lo cierto? La sobrecarga también se puede eliminar, porque tiene nombres infinitos para cada método.
1
y es por eso que obtuvimos la primavera y esas cosas que toman el lenguaje simple y convierten cualquier proyecto Java real en un grupo de sintaxis y repetitivo :-)
matanster
Forzar a los desarrolladores a código repetitivo y soluciones alternativas complicadas no es mi comprensión de la palabra "fácil". myFunction (a, b = false, c = 3), eso es lo que llamo fácil.
Spyro
5

En lugar 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
}

Puede utilizar la funcionalidad opcional de Java al tener un único método:

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

La principal diferencia es que debe usar clases de envoltura en lugar de tipos Java primitivos para permitir la nullentrada. Booleanen lugar de boolean, en Integerlugar de inty así sucesivamente.

Viktor Taranenko
fuente
4

No es compatible, pero hay varias opciones, como usar el patrón de objeto de parámetro con algo de azúcar de sintaxis:

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) {
    }
}

En este ejemplo construimos ParameterObjectcon valores predeterminados y los anulamos en la sección de inicialización de instancia de clase{ param1 = 10; param2 = "bar";}

hoaz
fuente
3

Prueba esta solución:

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

    return score;
}
Hamzeh Soboh
fuente
3

Puede usar Java Method Invocation Builder para generar automáticamente el generador con valores predeterminados.

Simplemente agregue @GenerateMethodInvocationBuilder a la clase o interfaz, y @Default a los parámetros en los métodos donde desea valores predeterminados. Se generará un generador en tiempo de compilación, utilizando los valores predeterminados que especificó con sus anotaciones.

@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;
 }
}

Y luego puedes invocar los métodos.

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

O establezca cualquiera de los valores predeterminados en otra cosa.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .withColor(Color.YELLOW)//
  .invoke(instance);
Tomás Bjerre
fuente
2

Un enfoque similar a https://stackoverflow.com/a/13864910/2323964 que funciona en Java 8 es utilizar una interfaz con captadores predeterminados. Esto será más detallado en espacios en blanco, pero se puede burlar, y es ideal para cuando tienes un montón de instancias en las que realmente quieres llamar la atención sobre los 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
fuente
2

Ahora he pasado bastante tiempo para descubrir cómo usar esto con métodos que devuelven valores, y hasta ahora no he visto ningún ejemplo, pensé que podría ser útil agregar esto aquí:

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

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

Así es como lo hice ... no es tan conveniente tal vez como tener un 'argumento opcional' contra su parámetro definido, pero hace el trabajo:

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 puedo invocar el mismo nombre de método con solo una cadena o puedo invocarlo con una cadena y un valor booleano. En este caso, establecer wipeClean en verdadero reemplazará todo el texto en mi TextArea con la cadena provista. Establecer wipeClean en falso o dejarlo todo junto simplemente agrega el texto proporcionado al TextArea.

También tenga en cuenta que no estoy repitiendo código en los dos métodos, simplemente estoy agregando la funcionalidad de poder restablecer TextArea creando un nuevo método con el mismo nombre solo con el booleano agregado.

De hecho, creo que esto es un poco más limpio que si Java proporcionara un 'argumento opcional' para nuestros parámetros, ya que tendríamos que codificar los valores predeterminados, etc. En este ejemplo, no necesito preocuparme por nada de eso. Sí, he agregado otro método a mi clase, pero a la larga es más fácil de leer en mi humilde opinión.

Michael Sims
fuente
1

NO, pero tenemos una alternativa en forma de sobrecarga de funciones.

llamado cuando no pasó ningún parámetro

void operation(){

int a = 0;
int b = 0;

} 

llamado cuando se pasó el parámetro "a"

void operation(int a){

int b = 0;
//code

} 

llamado cuando pasa el parámetro b

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

Hay media docena o más problemas como este, eventualmente, llega al patrón de fábrica estático ... vea la API de cifrado para eso. Es difícil de explicar, pero piénselo de esta manera: si tiene un constructor, predeterminado o no, la única forma de propagar el estado más allá de las llaves es tener un Boolean isValid; (junto con el nulo como valor predeterminado v constructor fallido) o arroje una excepción que nunca sea informativa al recuperarlo de los usuarios de campo.

Código Correcto, maldita sea, escribo mil constructores de líneas y hago lo que necesito. Encuentro usar isValid en la construcción de objetos, en otras palabras, constructores de dos líneas, pero por alguna razón, estoy migrando al patrón estático de fábrica. Parece que puede hacer mucho si en una llamada al método, todavía hay problemas de sync (), pero los valores predeterminados se pueden 'sustituir' mejor (más seguro)

Creo que lo que tenemos que hacer aquí es abordar el problema de nulo como valor predeterminado frente a algo String one = new String (""); como una variable miembro, luego realiza una comprobación de nulo antes de asignar la cadena pasada al constructor.

Muy notable la cantidad de informática en bruto estratosférica realizada en Java.

C ++ y demás tiene librerías de proveedores, sí. Java puede superarlos en servidores a gran escala debido a que es una caja de herramientas masiva. Estudie los bloques de inicializador estático, quédese con nosotros.

Nicholas Jordan
fuente
1

No es compatible en Java como en otro idioma para ex. Kotlin

Virendra Pal Singh
fuente
0

Puedes usar lo siguiente:

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