Esto puede ser algo común y trivial, pero me parece que estoy teniendo problemas para encontrar una respuesta concreta. En C# no es un concepto de delegados, en la que se relaciona fuertemente con la idea de punteros a funciones de C++. Hay una funcionalidad similar en Java? Dado que los punteros son un poco ausente, ¿cuál es la mejor manera acerca de esto? Y para ser claro, estamos hablando de primera clase aquí.

  • Yo sólo soy curioso en cuanto a por qué se quiere este, donde los oyentes o de otros OOP construir iba a hacer la misma tarea, mientras que la retención objeto de la naturaleza. Me refiero a que entiendan la necesidad de la funcionalidad ofrecida por el concepto de que se puede lograr con objeto normal.. a menos que, por supuesto, me estoy perdiendo algo, de ahí mi esta pregunta ! 🙂
  • Java 8 ha expresiones lambda: docs.oracle.com/javase/tutorial/java/javaOO/… es posible Que desee comprobar que fuera. No es un puntero a función, pero puede ser de más uso.
  • Java 8 método de referencias es exactamente lo que usted está pidiendo.
  • Java 8 método de referencias es exactamente lo que usted está pidiendo. this::myMethod es en esencia el mismo como la creación de un lambda paramA, paramB -> this.myMethod(paramA, paramB).
  • posibles duplicados de What es el más cercano sustituto de un puntero a función en Java?
InformationsquelleAutor Ben Lakey | 2009-07-02

11 Comentarios

  1. 125

    El lenguaje Java para la función de puntero como es la funcionalidad de una clase anónima implementación de una interfaz, por ejemplo,

    Collections.sort(list, new Comparator<MyClass>(){
        public int compare(MyClass a, MyClass b)
        {
            //compare objects
        }
    });

    Actualización: lo anterior es necesario en Java versiones anteriores de Java 8. Ahora tenemos mucho más agradable alternativas, a saber lambdas:

    list.sort((a, b) -> a.isGreaterThan(b));

    y método de referencias:

    list.sort(MyClass::isGreaterThan);
    • La Estrategia patrón de diseño. No tan fea como C o C++ puntero de función cuando se desea que la función para utilizar algunos de los datos globales que no es proporcionado como argumento a la función.
    • C++ tiene functors, y C++0x ha cierres y las lambdas construido en la parte superior de functors. Incluso tiene std::bind, que se une parámetros a funciones y devuelve un objeto invocable. Yo no puedo defender a C por estos motivos, pero C++ realmente es mejor que Java para esto.
    • Bien, C++0x, podría ser, pero el actual estándar de C++ no es.
    • Usted puede hacer esto en C pasando a lo largo de un puntero a los datos del usuario (por ejemplo: struct). (y puede encapsular con cada nuevo nivel de devolución de llamada de direccionamiento indirecto) Es en realidad bastante limpio.
    • Sí, voy a tomar realmente C punteros a función más crufty clases de contenedor de cualquier día
    • eso es lo que los delegados en C# son para! Son limpios, seguridad de tipos punteros a función.
    • Java 8 tiene una mejor sintaxis para esto.

  2. 63

    Puede substitue un puntero a función con una interfaz. Digamos que usted desea ejecutar a través de una colección y hacer algo con cada elemento.

    public interface IFunction {
      public void execute(Object o);
    }

    Esta es la interfaz que nos podría pasar a algunos decir CollectionUtils2.doFunc(Colección c, IFunction f).

    public static void doFunc(Collection c, IFunction f) {
       for (Object o : c) {
          f.execute(o);
       }
    }

    Como un ejemplo, digamos que tenemos una colección de números y te gustaría agregar 1 a cada elemento.

    CollectionUtils2.doFunc(List numbers, new IFunction() {
        public void execute(Object o) {
           Integer anInt = (Integer) o;
           anInt++;
        }
    });
    • Es posible que desee agregar que los genéricos que…
  3. 41

    Puede utilizar la reflexión para hacerlo.

    Pasar como parámetro el objeto y el nombre del método (como una cadena) y, a continuación, invocar el método. Por ejemplo:

    Object methodCaller(Object theObject, String methodName) {
       return theObject.getClass().getMethod(methodName).invoke(theObject);
       //Catch the exceptions
    }

    Y, a continuación, utilizarlo como en:

    String theDescription = methodCaller(object1, "toString");
    Class theClass = methodCaller(object2, "getClass");

    Por supuesto, comprobar que todas las excepciones y añadir el yeso.

    • Esto es 1. feo y 2. lento. Pero todavía una respuesta válida. 😉
    • La reflexión no es la respuesta correcta a cualquier cosa excepto «¿Cómo escribo lento chunga código de java» 😀
    • Podría ser «feo» y lento, pero creo que la reflexión permite hacer cosas que la interfaz de la solución basada en la aceptación de la respuesta no puede hacer (a menos que me equivoco), es decir, la llamada de varios métodos del mismo objeto en la misma parte de código.
    • Me pasaba por este post y tenia una duda.. por lo que en su enfoque, si puedo acceder a la variable «theDescription», la función se llama a cada uno y cada vez que se accede??
  4. 20

    No, las funciones no son objetos de primera clase en java. Usted puede hacer lo mismo mediante la implementación de un controlador de clase – esto es cómo las devoluciones de llamada se implementan en el Swing, etc.

    Sin embargo, hay propuestas para cierres (el nombre oficial de lo que estamos hablando) en futuras versiones de java – Javaworld tiene un artículo interesante.

    • Muy interesante, gracias por la información.
  5. 8

    Para lograr una funcionalidad similar podría utilizar las clases internas anónimas.

    Si se va a definir una interfaz Foo:

    interface Foo {
        Object myFunc(Object arg);
    }

    Crear un método bar que va a recibir un puntero a la función de’ como un argumento:

    public void bar(Foo foo) {
        //.....
        Object object = foo.myFunc(argValue);
        //.....
    }

    Finalmente llamar al método de la siguiente manera:

    bar(new Foo() {
        public Object myFunc(Object arg) {
            //Function code.
        }
    }
  6. 6

    Java8 ha introducido lambdas y método de referencias. Así que si su función coincide con un características funcionales de la interfaz (usted puede crear su propia) se puede utilizar un método de referencia en este caso.

    Java proporciona un conjunto de común de interfaces funcionales. mientras que usted podría hacer lo siguiente:

    public class Test {
       public void test1(Integer i) {}
       public void test2(Integer i) {}
       public void consumer(Consumer<Integer> a) {
         a.accept(10);
       }
       public void provideConsumer() {
         consumer(this::test1);   //method reference
         consumer(x -> test2(x)); //lambda
       }
    }
  7. 5

    No hay tal cosa en Java. Usted tendrá que envolver su función en algún objeto y pasar la referencia a ese objeto con el fin de pasar la referencia para el método en el objeto.

    Sintácticamente, esto puede ser aliviado en cierta medida por el uso anónimo de las clases definidas en el lugar o anónima, las clases se definen como variables miembro de la clase.

    Ejemplo:

    class MyComponent extends JPanel {
        private JButton button;
        public MyComponent() {
            button = new JButton("click me");
            button.addActionListener(buttonAction);
            add(button);
        }
    
        private ActionListener buttonAction = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //handle the event...
                //note how the handler instance can access 
                //members of the surrounding class
                button.setText("you clicked me");
            }
        }
    }
  8. 3

    He implementado de devolución de llamada/delegado de soporte en Java utilizando la reflexión. Los detalles y el trabajo de la fuente son disponible en mi sitio web.

    Cómo Funciona

    Tenemos un principio de la clase nombre de devolución de llamada con una clase anidada nombre WithParms. La API de que las necesidades de la devolución de llamada de tomar un objeto de devolución de llamada como un parámetro y, si es necesario, crear una devolución de llamada.WithParms como un método de variable. Dado que muchas de las aplicaciones de este objeto va a ser recursivo, esto funciona muy limpia.

    Con el rendimiento todavía una alta prioridad para mí, no quería que se requiere para crear un objeto de usar y tirar matriz para mantener los parámetros para cada invocación – después de todo, en una gran estructura de datos no podría ser de miles de elementos, y en un mensaje de procesamiento de escenario que podría terminar de procesar miles de estructuras de datos de un segundo.

    Con el fin de ser threadsafe el parámetro de la matriz de necesidades que existen de forma exclusiva para cada invocación del método de la API, y para la eficiencia de la misma debe ser utilizado para cada invocación de la devolución de llamada; necesitaba un segundo objeto que sería barato a crear con el fin de obligar a la devolución de llamada con una matriz de parámetros de la invocación. Pero, en algunos casos, el invocador ya habría un la matriz de parámetros por otras razones. Por estas dos razones, la matriz de parámetros no pertenecen al objeto de devolución de llamada. También la elección de la invocación (que pasa los parámetros como una matriz o como objetos individuales) debe estar en manos de la API usando la devolución de llamada que permite el uso de cualquiera de invocación es el más adecuado a su funcionamiento interno.

    La WithParms clase anidada, entonces, es opcional y sirve para dos propósitos, que contiene el parámetro array de objetos necesarios para la devolución de las invocaciones, y ofrece 10 sobrecargado invoke() métodos (con de 1 a 10 parámetros) que la carga de la matriz de parámetros y, a continuación, invocar la devolución de llamada de destino.

  9. -1

    Relativo a la mayoría de la gente de aquí soy nuevo en java, pero ya no he visto una similar sugerencia que tengo otra alternativa para sugerir. No estoy seguro si es una buena práctica o no, o incluso se ha sugerido antes, y yo simplemente no lo entendía. Me gusta ya que creo que su auto descriptivo.

     /*Just to merge functions in a common name*/
     public class CustomFunction{ 
     public CustomFunction(){}
     }
    
     /*Actual functions*/
     public class Function1 extends CustomFunction{
     public Function1(){}
     public void execute(){...something here...}
     }
    
     public class Function2 extends CustomFunction{
     public Function2(){}
     public void execute(){...something here...}
     }
    
     .....
     /*in Main class*/
     CustomFunction functionpointer = null;

    a continuación, dependiendo de la aplicación, asignar

     functionpointer = new Function1();
     functionpointer = new Function2();

    etc.

    y llamar por

     functionpointer.execute();

Dejar respuesta

Please enter your comment!
Please enter your name here