Digamos que eu tenha a seguinte interface funcional no Java 8:
interface Action<T, U> {
U execute(T t);
}
E, em alguns casos, preciso de uma ação sem argumentos ou tipo de retorno. Então eu escrevo algo assim:
Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };
No entanto, isso me dá erro de compilação, preciso escrevê-lo como
Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};
O que é feio. Existe alguma maneira de se livrar do Void
parâmetro type?
Runnable
, o que você está procurando #Runnable r = () -> System.out.println("Do nothing!");
Respostas:
A sintaxe que você procura é possível com uma pequena função auxiliar que converte um
Runnable
emAction<Void, Void>
(você pode colocá-lo,Action
por exemplo):fonte
@FunctionalInterface
. Ele simplesmente diz que não é possível estendê-lo ...Runnable
ação, deve-se adotar@FunctionalInterface
algo personalizadoSideEffect
, 2. a necessidade dessa função auxiliar destaca que algo estranho está acontecendo e provavelmente a abstração está quebrada.Use
Supplier
se não levar nada, mas retornar algo.Use
Consumer
se for preciso algo, mas não retorna nada.Use
Callable
se retornar um resultado e pode ser lançado (mais parecido comThunk
termos gerais de CS).Use
Runnable
se não fizer nada e não puder jogar.fonte
public static void wrapCall(Runnable r) { r.run(); }
. ObrigadoO lambda:
na verdade representa uma implementação para uma interface como:
que é completamente diferente daquele que você definiu. É por isso que você recebe um erro.
Como você não pode estender o seu
@FunctionalInterface
, nem introduzir um novo, acho que você não tem muitas opções. Você pode usar asOptional<T>
interfaces para indicar que alguns dos valores (tipo de retorno ou parâmetro do método) estão ausentes. No entanto, isso não tornará o corpo lambda mais simples.fonte
Something
função não pode ser um subtipo do meuAction
tipo e não posso ter dois tipos diferentes.Você pode criar uma sub-interface para esse caso especial:
Ele usa um método padrão para substituir o método parametrizado herdado
Void execute(Void)
, delegando a chamada ao método mais simplesvoid execute()
.O resultado é que é muito mais simples de usar:
fonte
Action<T, U>
está declarado na pergunta .....Eu acho que esta tabela é curta e útil:
Como dito nas outras respostas, a opção apropriada para esse problema é uma
Runnable
fonte
Isso não é possível. Uma função que possui um tipo de retorno não nulo (mesmo que seja
Void
) deve retornar um valor. No entanto, você pode adicionar métodos estáticos aoAction
que permite "criar" aAction
:Isso permitiria escrever o seguinte:
fonte
Adicione um método estático dentro da sua interface funcional
Resultado
fonte
Eu não acho que é possível, porque as definições de função não correspondem no seu exemplo.
Sua expressão lambda é avaliada exatamente como
enquanto sua declaração parece
como exemplo, se você tiver a seguinte interface
o único tipo de função (ao instanciar) que será compatível parece
e a declaração ou argumento da falta de retorno fornecerá um erro do compilador.
Portanto, se você declarar uma função que recebe um argumento e retorna um, acho que é impossível convertê-lo em uma função que não menciona acima.
fonte
Apenas para referência, qual interface funcional pode ser usada para referência de método nos casos em que o método lança e / ou retorna um valor.
fonte