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 Void
parámetro type?
Runnable
lo que está buscandoRunnable r = () -> System.out.println("Do nothing!");
Respuestas:
La sintaxis que busca es posible con una pequeña función auxiliar que convierte a
Runnable
enAction<Void, Void>
(puede colocarla,Action
por ejemplo):fuente
@FunctionalInterface
. Simplemente dice que no es posible extenderlo ...Runnable
tomar una acción personalizada, debería@FunctionalInterface
llamarse algoSideEffect
2. La necesidad de dicha función auxiliar resalta que algo extraño está sucediendo y probablemente la abstracción está rota.Úselo
Supplier
si no toma nada, pero devuelve algo.Úselo
Consumer
si toma algo, pero no devuelve nada.Úselo
Callable
si devuelve un resultado y podría arrojar (más parecidoThunk
en términos generales de CS).Úselo
Runnable
si no lo hace y no puede lanzar.fuente
public static void wrapCall(Runnable r) { r.run(); }
. GraciasLa lambda:
en realidad representa una implementación para una interfaz como:
que es completamente diferente al que has definido. Es por eso que obtienes un error.
Como no puede extender su
@FunctionalInterface
, ni introducir uno nuevo, creo que no tiene muchas opciones. SinOptional<T>
embargo, puede usar las interfaces 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.fuente
Something
función no puede ser un subtipo de miAction
tipo y no puedo tener dos tipos diferentes.Puede crear una subinterfaz para ese caso especial:
Utiliza un método predeterminado para anular el método parametrizado heredado
Void execute(Void)
, delegando la llamada al método más simplevoid execute()
.El resultado es que es mucho más simple de usar:
fuente
Action<T, U>
se declara en la pregunta .....Creo que esta tabla es corta y útil:
Como se dijo en las otras respuestas, la opción adecuada para este problema es un
Runnable
fuente
Eso no es posible. Una función que tiene un tipo de retorno no nulo (incluso si es
Void
) tiene que devolver un valor. Sin embargo, podría agregar métodos estáticosAction
que le permitan "crear" aAction
:Eso te permitiría escribir lo siguiente:
fuente
Agregue un método estático dentro de su interfaz funcional
Salida
fuente
No creo que sea posible, porque las definiciones de funciones no coinciden en su ejemplo.
Su expresión lambda se evalúa exactamente como
mientras que su declaración parece
como ejemplo, si tiene la siguiente interfaz
el único tipo de función (durante la creación de instancias) que será compatible parece
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.
fuente
Solo como referencia, qué interfaz funcional se puede usar para referencia de método en casos en los que el método arroja y / o devuelve un valor.
fuente