Existe uma maneira de passar uma função de retorno de chamada em um método Java?
O comportamento que estou tentando imitar é um .Net Delegate sendo passado para uma função.
Eu já vi pessoas sugerindo a criação de um objeto separado, mas isso parece exagero, no entanto, estou ciente de que, às vezes, exagero é a única maneira de fazer as coisas.
java
callback
function-pointers
Omar Kooheji
fonte
fonte
Respostas:
Se você quer dizer algo como o delegado anônimo do .NET, acho que a classe anônima do Java também pode ser usada.
fonte
Desde o Java 8, existem referências lambda e método:
Por exemplo, se você deseja uma interface funcional
A -> B
como:então você pode chamar assim
Além disso, você pode passar o método de classe. Digamos que você tenha:
Então você pode fazer:
Nota :
Aqui eu usei a interface funcional
Function<A,B>
, mas há muitas outras no pacotejava.util.function
. Os mais notáveis sãoSupplier
:void -> A
Consumer
:A -> void
BiConsumer
:(A,B) -> void
Function
:A -> B
BiFunction
:(A,B) -> C
e muitos outros que se especializam em alguns tipos de entrada / saída. Então, se ele não fornecer o necessário, você poderá criar sua própria interface funcional da seguinte maneira:
Exemplo de uso:
fonte
java.util.function
é o que você está procurando, então você está pronto. Então você pode jogar com genéricos para a E / S. (?)java.util.function
não são suficientes.Para simplificar, você pode usar um Runnable :
Uso:
fonte
public interface SimpleCallback { void callback(Object... objects); }
Isso é bastante direto e pode ser útil, você também precisa passar por alguns parâmetros.Um pouco de nitpicking:
A passagem de um retorno de chamada inclui a criação de um objeto separado em praticamente qualquer linguagem OO, portanto, dificilmente pode ser considerado um exagero. O que você provavelmente quer dizer é que, em Java, é necessário criar uma classe separada, que é mais detalhada (e consome mais recursos) do que nas linguagens com funções ou fechamentos explícitos de primeira classe. No entanto, classes anônimas pelo menos reduzem a verbosidade e podem ser usadas em linha.
fonte
no entanto, vejo que há a maneira mais preferida, que era o que eu estava procurando ... é basicamente derivado dessas respostas, mas eu tive que manipulá-lo para mais redundante e eficiente .. e acho que todo mundo procurando o que eu acho
Ao ponto::
primeiro faça uma interface tão simples
Agora, para fazer com que esse retorno de chamada seja executado sempre que desejar, para lidar com os resultados - mais provavelmente após uma chamada assíncrona e você deseja executar algumas coisas que dependem dessas reutilizações
doSomething
é a função que leva algum tempo em que você deseja adicionar um retorno de chamada para notificá-lo quando os resultados vierem, adicione a interface de retorno de chamada como parâmetro a esse métodoespero que meu ponto seja claro, aproveite;)
fonte
Isso é muito fácil no Java 8 com lambdas.
fonte
Achei interessante a ideia de implementar usando a biblioteca reflect e cheguei a isso que acho que funciona muito bem. O único lado negativo é perder a verificação do tempo de compilação de que você está passando parâmetros válidos.
Você usa assim
fonte
Um método ainda não é um objeto de primeira classe em Java; você não pode passar um ponteiro de função como retorno de chamada. Em vez disso, crie um objeto (que geralmente implementa uma interface) que contém o método necessário e passe-o.
Propostas de fechamento em Java - que forneceriam o comportamento que você procura - foram feitas, mas nenhuma será incluída na próxima versão do Java 7.
fonte
Quando preciso desse tipo de funcionalidade em Java, geralmente uso o padrão Observer . Isso implica em um objeto extra, mas acho que é um caminho limpo, e é um padrão amplamente compreendido, que ajuda na legibilidade do código.
fonte
Verifique os fechamentos como eles foram implementados na biblioteca lambdaj. Na verdade, eles têm um comportamento muito semelhante aos delegados em C #:
http://code.google.com/p/lambdaj/wiki/Closures
fonte
Eu tentei usar java.lang.reflect para implementar 'callback', aqui está um exemplo:
fonte
timer.SetTimer ((int)(Math.random ()*10), System.out, "printf", "%s: [%s]", new Object[]{"null test", null});
. saída seránull test: [null]
args[i].getClass()
? Meu argumento é que não funcionará se você selecionar o método com base nos tipos de argumento. Funciona comString.format
, mas pode não funcionar com outra coisa que aceitenull
.argTypes
matriz, para que agora possamos passar onull
argumento / parâmetro sem a ocorrência de NullPointerException. Exemplo de saída:NullParameterTest: String parameter=null, int parameter=888
Você também pode fazer o
Callback
uso doDelegate
padrão:Callback.java
PagerActivity.java
CustomPagerAdapter.java
fonte
Recentemente, comecei a fazer algo assim:
fonte
é um pouco antigo, mas, no entanto ... achei a resposta de Peter Wilkinson agradável, exceto pelo fato de que não funciona para tipos primitivos como int / Integer. O problema é
.getClass()
forparameters[i]
, que retorna por exemplojava.lang.Integer
, que por outro lado não será corretamente interpretado porgetMethod(methodName,parameters[])
(falha de Java) ...Combinei-o com a sugestão de Daniel Spiewak ( em sua resposta a isso ); os passos para o sucesso incluíam: pegar
NoSuchMethodException
->getMethods()
-> procurar o correspondente pormethod.getName()
-> e, em seguida, percorrer explicitamente a lista de parâmetros e aplicar a solução Daniels, como identificar as correspondências de tipo e de assinatura.fonte
Eu acho que usar uma classe abstrata é mais elegante, assim:
fonte
object
"notificar" outroobject
quando algo significativo ocorreu, para que o segundoobject
possa manipular o evento. Vocêabstract class
nunca é um separadoobject
, é apenas um separadoclass
. Você está usando apenas umobject
e se diferenciandoclasses
para executar funções diferentes, que é a essência do polimorfismo, não o padrão de retorno de chamada.Basicamente, se você deseja criar o objeto de uma interface, isso não é possível, porque a interface não pode ter objetos.
A opção é permitir que alguma classe implemente a interface e depois chame essa função usando o objeto dessa classe. Mas essa abordagem é realmente detalhada.
Como alternativa, escreva new HelloWorld () (* observe que essa é uma interface, não uma classe) e siga-a com a definição dos métodos da interface. (* Esta definição é na realidade a classe anônima). Então você obtém a referência do objeto através da qual você pode chamar o próprio método.
fonte
Crie uma interface e crie a mesma propriedade de interface na classe de retorno de chamada.
Agora na classe em que você deseja ser chamado de volta, implemente a Interface criada acima. e também passe "este" Objeto / Referência da sua classe para ser chamado de volta.
fonte