valores valor tipos por parametros opcionales los long defecto datos java methods parameters default-value method-overloading

parametros - valores por defecto de los tipos de datos en java



¿Java soporta valores de parámetros por defecto? (19)

Me encontré con 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 un parámetro a un valor predeterminado. Por ejemplo:

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

¿Java soporta este tipo de sintaxis? ¿Hay alguna razón por la que esta sintaxis de dos pasos sea preferible?


Así es como lo hice ... no es tan conveniente tal vez como tener un ''argumento opcional'' en contra de 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"); }

Note 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 true reemplazará todo el texto en mi TextArea con la cadena provista. Al establecer wipeClean en falso o dejarlo todo junto, simplemente se agrega el texto proporcionado a TextArea.

También tenga en cuenta que no estoy repitiendo el 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 tengo que 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.


Como se mencionó a Scala, también vale la pena mencionar a Kotlin . En la función de 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 se puede integrar fácilmente en proyectos Java existentes.


Hay media docena o mejores problemas como este, eventualmente llegas al patrón de fábrica estático ... mira la api de cripto 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 valor booleano isValid; (junto con el valor nulo como valor predeterminado del constructor fallido) o lanzar una excepción que nunca es informativa cuando se lo devuelve a los usuarios de campo.

Maldición del código correcto, escribo miles de constructores de líneas y hago lo que necesito. Encuentro el uso de isValid en la construcción de objetos, en otras palabras, dos constructores de líneas, pero por alguna razón estoy migrando al patrón de fábrica estático. Parece que puede hacer mucho si en una llamada de método, todavía hay problemas de sincronización (), pero los valores predeterminados pueden ser "sustituidos" mejor (más seguros)

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

Muy notable la cantidad de ciencia computacional estratosférica en bruto realizada en Java.

C ++ y así sucesivamente tiene librerías, sí. Java puede superarlos en servidores a gran escala debido a su enorme caja de herramientas. Estudia los bloques de inicialización estática, quédate con nosotros.


Hay varias formas de simular los 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, perderá la verificació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 utiliza la clase opcional de Java 8 para los 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 tal firma demasiado detallada.

  5. Patrón constructor. El patrón de constructor se usa para los constructores y se implementa introduciendo una clase de Generador 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 normalmente 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.


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

se llama cuando no se pasa ningún parámetro

void operation(){ int a = 0; int b = 0; }

se llama cuando se pasa el parámetro "a"

void operation(int a){ int b = 0; //code }

se llama cuando se pasa el parámetro b

void operation(int a , int b){ //code }


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

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 ParameterObject con valores predeterminados y los reemplazamos en la sección de inicialización de instancia de clase { param1 = 10; param2 = "bar";} { param1 = 10; param2 = "bar";}


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

Para constructores, vea la sugerencia del Artículo 1 de Effective Java: Programming Language Guide (Considere los métodos estáticos de fábrica en lugar de los constructores) si la sobrecarga se está complicando. 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 para que la diferenciación sea difícil. Un caso concreto es cuando debe diferenciarse utilizando el orden de los parámetros, no solo el número y el tipo.


No, pero puede usar el patrón de creación , 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.


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

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 causaban casos ambiguos en la sobrecarga de funciones. Eso simplemente no es cierto, podemos ver en el caso de C ++: sí, quizás pueda crear casos ambiguos, pero este problema se puede manejar fácilmente. Simplemente no se desarrolló en Java, probablemente porque los creadores querían un lenguaje mucho más simple como C ++, si tenían razón, es otra pregunta. Pero la mayoría de nosotros no creemos que use Java debido a su simplicidad.


No.

Puede lograr el mismo comportamiento pasando un Objeto que tiene valores predeterminados inteligentes. Pero otra vez depende de lo que su caso está a la mano.


No. En general, Java no tiene mucha azúcar sintáctica, ya que intentaron hacer un lenguaje simple.


Por desgracia sí.

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

Se podría escribir 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 depende o no 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) {}

Se podría escribir 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, hay una diferencia en la que este tipo de tiempo de ejecución verifica los parámetros predeterminados pasados ​​y el tipo C ++ los verifica durante la compilación.


Pruebe esta solución:

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


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

es decir

class Foo(var prime: Boolean = false, val rib: String) {}


Puede que esté indicando lo obvio aquí, pero ¿por qué no implementar el parámetro "predeterminado"?

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

para el valor predeterminado sería el uso de éter

func ("mi cuerda");

y si no desea utilizar el valor predeterminado, debe utilizar

func ("mi cadena", falso);


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

Simplemente agregue @GenerateMethodInvocationBuilder a la clase o interfaz, y @Default a los parámetros en los métodos en los que desea valores predeterminados. Se generará un generador en el momento de la 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 a otra cosa.

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


Tristemente no.


Un enfoque similar a https://.com/a/13864910/2323964 que funciona en Java 8 es usar una interfaz con los getters predeterminados. Esto será más espacio en blanco, pero se puede simular, y es ideal para cuando tiene un montón de casos en los que realmente desea 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; } }); } }


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 utilizar si:

public myParameterizedFunction(String param1, int param2, Boolean param3) { if (param3 == null) { param3 = false; } } public myParameterizedFunction(String param1, int param2) { this(param1, param2, false); }