usar tutorial lambdas expresiones explicacion espaƱol ejemplos como java lambda java-8 void

tutorial - Argumento de Java 8 lambda Void



java 8 lambdas pdf (8)

Digamos que tengo la siguiente interfaz funcional en Java 8:

interface Action<T, U> { U execute(T t); }

Y para algunos casos necesito una acción sin argumentos o tipo de retorno. Entonces escribo algo como esto:

Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };

Sin embargo, me da un error de compilación, necesito escribirlo como

Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};

Lo cual es feo. ¿Hay alguna forma de deshacerse del parámetro de tipo Void ?


Agregue un método estático dentro de su interfaz funcional

package example; interface Action<T, U> { U execute(T t); static Action<Void,Void> invoke(Runnable runnable){ return (v) -> { runnable.run(); return null; }; } } public class Lambda { public static void main(String[] args) { Action<Void, Void> a = Action.invoke(() -> System.out.println("Do nothing!")); Void t = null; a.execute(t); } }

Salida

Do nothing!


Eso no es posible. Una función que tiene un tipo de retorno no nulo (incluso si es nula) tiene que devolver un valor. Sin embargo, podría agregar métodos estáticos a la Action que le permitan "crear" una Action :

interface Action<T, U> { U execute(T t); public static Action<Void, Void> create(Runnable r) { return (t) -> {r.run(); return null;}; } public static <T, U> Action<T, U> create(Action<T, U> action) { return action; } }

Eso te permitiría escribir lo siguiente:

// create action from Runnable Action.create(()-> System.out.println("Hello World")).execute(null); // create normal action System.out.println(Action.create((Integer i) -> "number: " + i).execute(100));


La lambda:

() -> { System.out.println("Do nothing!"); };

en realidad representa una implementación para una interfaz como:

public interface Something { void action(); }

que es completamente diferente a la que has definido. Es por eso que obtienes un error.

Como no puede extender su @FunctionalInterface , ni introducir una nueva, entonces creo que no tiene muchas opciones. Sin embargo, puede usar las interfaces Optional<T> para denotar que faltan algunos de los valores (tipo de retorno o parámetro de método). Sin embargo, esto no hará que el cuerpo lambda sea más simple.


La sintaxis que Runnable es posible con una pequeña función auxiliar que convierte un Runnable en Action<Void, Void> (puede colocarlo en Action por ejemplo):

public static Action<Void, Void> action(Runnable runnable) { return (v) -> { runnable.run(); return null; }; } // Somewhere else in your code Action<Void, Void> action = action(() -> System.out.println("foo"));


No creo que sea posible, porque las definiciones de funciones no coinciden en su ejemplo.

Su expresión lambda se evalúa exactamente como

void action() { }

mientras que su declaración parece

Void action(Void v) { //must return Void type. }

como ejemplo, si tiene la siguiente interfaz

public interface VoidInterface { public Void action(Void v); }

el único tipo de función (durante la creación de instancias) que será compatible parece

new VoidInterface() { public Void action(Void v) { //do something return v; } }

y la falta de declaración o argumento de devolución le dará un error de compilación.

Por lo tanto, si declara una función que toma un argumento y devuelve uno, creo que es imposible convertirlo en una función que no menciona ninguno de los anteriores.


Puede crear una subinterfaz para ese caso especial:

interface Command extends Action<Void, Void> { default Void execute(Void v) { execute(); return null; } void execute(); }

Utiliza un método predeterminado para anular el método parametrizado heredado Void execute(Void) , delegando la llamada al método más simple void execute() .

El resultado es que es mucho más simple de usar:

Command c = () -> System.out.println("Do nothing!");


Solo como referencia, qué interfaz funcional se puede usar para referencia de método en casos en que el método arroja y / o devuelve un valor.

void notReturnsNotThrows() {}; void notReturnsThrows() throws Exception {} String returnsNotThrows() { return ""; } String returnsThrows() throws Exception { return ""; } { Runnable r1 = this::notReturnsNotThrows; //ok Runnable r2 = this::notReturnsThrows; //error Runnable r3 = this::returnsNotThrows; //ok Runnable r4 = this::returnsThrows; //error Callable c1 = this::notReturnsNotThrows; //error Callable c2 = this::notReturnsThrows; //error Callable c3 = this::returnsNotThrows; //ok Callable c4 = this::returnsThrows; //ok } interface VoidCallableExtendsCallable extends Callable<Void> { @Override Void call() throws Exception; } interface VoidCallable { void call() throws Exception; } { VoidCallableExtendsCallable vcec1 = this::notReturnsNotThrows; //error VoidCallableExtendsCallable vcec2 = this::notReturnsThrows; //error VoidCallableExtendsCallable vcec3 = this::returnsNotThrows; //error VoidCallableExtendsCallable vcec4 = this::returnsThrows; //error VoidCallable vc1 = this::notReturnsNotThrows; //ok VoidCallable vc2 = this::notReturnsThrows; //ok VoidCallable vc3 = this::returnsNotThrows; //ok VoidCallable vc4 = this::returnsThrows; //ok }


Use el Supplier si no toma nada, pero devuelve algo.

Use Consumer si toma algo, pero no devuelve nada.

Use Callable si devuelve un resultado y podría arrojar (más parecido a Thunk en términos generales de CS).

Use Runnable si no lo hace y no puede lanzar.