¿Hay alguna manera de pasar una función de devolución de llamada en un método Java?
El comportamiento que intento imitar es un delegado .Net que se pasa a una función.
He visto personas sugiriendo crear un objeto separado, pero eso parece excesivo, sin embargo, soy consciente de que a veces el exceso es la única forma de hacer las cosas.
java
callback
function-pointers
Omar Kooheji
fuente
fuente
Respuestas:
Si te refieres a algo como delegado anónimo .NET, creo que la clase anónima de Java también se puede usar.
fuente
Desde Java 8, hay referencias lambda y de métodos:
Por ejemplo, si desea una interfaz funcional
A -> B
como:entonces puedes llamarlo así
También puedes pasar el método de clase. Digamos que tienes:
Entonces puedes hacer:
Nota :
Aquí utilicé la interfaz funcional
Function<A,B>
, pero hay muchos otros en el paquetejava.util.function
. Los más notables sonSupplier
:void -> A
Consumer
:A -> void
BiConsumer
:(A,B) -> void
Function
:A -> B
BiFunction
:(A,B) -> C
y muchos otros que se especializan en algunos de los tipos de entrada / salida. Luego, si no proporciona el que necesita, puede crear su propia interfaz funcional de la siguiente manera:
Ejemplo de uso:
fuente
java.util.function
es lo que estás buscando, entonces estás listo para comenzar. Entonces puedes jugar con genéricos para la E / S. (?)java.util.function
no son suficientes.Para simplificar, puede usar un Runnable :
Uso:
fuente
public interface SimpleCallback { void callback(Object... objects); }
Esto es bastante sencillo y podría ser útil si necesita pasar algunos parámetros también.Un pequeño truco:
Pasar una devolución de llamada incluye crear un objeto separado en prácticamente cualquier lenguaje OO, por lo que difícilmente se puede considerar excesivo. Lo que probablemente quiere decir es que en Java, requiere que cree una clase separada, que es más detallada (y más intensiva en recursos) que en lenguajes con funciones explícitas o cierres de primera clase. Sin embargo, las clases anónimas al menos reducen la verbosidad y se pueden usar en línea.
fuente
Sin embargo, veo que es la forma más preferida, que era lo que estaba buscando ... básicamente se deriva de estas respuestas, pero tuve que manipularlo para que sea más redundante y eficiente ... y creo que todos buscan lo que se me ocurrió.
Al punto::
primero haga una interfaz así de simple
ahora para hacer que esta devolución de llamada se ejecute siempre que desee hacer para manejar los resultados, más probable después de una llamada asincrónica y desea ejecutar algunas cosas que dependen de estos reinicios
doSomething
es la función que lleva algún tiempo que desee agregarle una devolución de llamada para notificarle cuándo llegaron los resultados, agregue la interfaz de devolución de llamada como parámetro de este métodoespero que mi punto sea claro, disfruta;)
fuente
Esto es muy fácil en Java 8 con lambdas.
fuente
La idea de implementar usando la biblioteca reflect me pareció interesante y se me ocurrió esto, que creo que funciona bastante bien. El único inconveniente es perder el tiempo de compilación de que está pasando parámetros válidos.
Lo usas así
fuente
Un método no es (todavía) un objeto de primera clase en Java; no puede pasar un puntero de función como devolución de llamada. En su lugar, cree un objeto (que generalmente implementa una interfaz) que contiene el método que necesita y páselo.
Se han hecho propuestas para cierres en Java, que proporcionarían el comportamiento que está buscando, pero ninguna se incluirá en la próxima versión de Java 7.
fuente
Cuando necesito este tipo de funcionalidad en Java, generalmente uso el patrón Observer . Sí implica un objeto extra, pero creo que es un camino limpio, y es un patrón ampliamente entendido, que ayuda con la legibilidad del código.
fuente
Compruebe los cierres cómo se han implementado en la biblioteca lambdaj. Realmente tienen un comportamiento muy similar al de los delegados de C #:
http://code.google.com/p/lambdaj/wiki/Closures
fuente
Intenté usar java.lang.reflect para implementar 'devolución de llamada', aquí hay una muestra:
fuente
timer.SetTimer ((int)(Math.random ()*10), System.out, "printf", "%s: [%s]", new Object[]{"null test", null});
. la salida seránull test: [null]
args[i].getClass()
? Mi punto es que no funciona si selecciona un método basado en tipos de argumento. Funciona conString.format
, pero puede no funcionar con otra cosa que aceptenull
.argTypes
matriz, por lo que ahora podemos pasarnull
argumentos / parámetros sin que ocurra NullPointerException. Salida de muestra:NullParameterTest: String parameter=null, int parameter=888
También puedes hacer el
Callback
uso delDelegate
patrón:Callback.java
PagerActivity.java
CustomPagerAdapter.java
fuente
Recientemente comencé a hacer algo como esto:
fuente
es un poco viejo, pero sin embargo ... la respuesta de Peter Wilkinson me pareció agradable, excepto por el hecho de que no funciona para tipos primitivos como int / Integer. El problema es
.getClass()
para elparameters[i]
, que devuelve por ejemplojava.lang.Integer
, que por otro lado no será interpretado correctamente porgetMethod(methodName,parameters[])
(culpa de Java) ...Lo combiné con la sugerencia de Daniel Spiewak ( en su respuesta a esto ); los pasos para el éxito incluyeron: capturar
NoSuchMethodException
->getMethods()
-> buscar la coincidencia pormethod.getName()
-> y luego recorrer explícitamente la lista de parámetros y aplicar la solución Daniels, como identificar las coincidencias de tipo y las coincidencias de firma.fuente
Creo que usar una clase abstracta es más elegante, así:
fuente
object
"notifique" a otroobject
cuando ha ocurrido algo significativo, para que el segundoobject
pueda manejar el evento. Tuabstract class
nunca es un separadoobject
, es solo un separadoclass
. Solo está utilizando unoobject
y se está volviendo diferenteclasses
para realizar diferentes funciones, que es la esencia del polimorfismo, no el patrón de devolución de llamada.Básicamente, si desea hacer que el objeto de una interfaz no sea posible, porque la interfaz no puede tener objetos.
La opción es dejar que alguna clase implemente la interfaz y luego llamar a esa función usando el objeto de esa clase. Pero este enfoque es realmente detallado.
Alternativamente, escriba un nuevo HelloWorld () (* observe que esta es una interfaz, no una clase) y luego siga con la definición de los métodos de interfaz en sí. (* Esta definición es en realidad la clase anónima). Luego obtienes la referencia del objeto a través del cual puedes llamar al método en sí.
fuente
Cree una interfaz y cree la misma propiedad de interfaz en la clase de devolución de llamada.
Ahora, en la clase donde desea que le devuelvan la llamada, implemente la interfaz creada anteriormente. y también pase "este" objeto / referencia de su clase para que se le devuelva la llamada.
fuente