Friday, December 22, 2017

Use MethodHandle to dynamically invoke method

MethodHandle is introduced in Java 7. For dynamic method invoking, it is faster than reflection.

In the code below, class MethodHandleTest2 has three JTextField fields and an objModified method. When any of the JTextField fields is modified, the objModified method will be called to handle the modification accordingly.

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class MethodHandleTest2 extends JFrame{
    public MethodHandleTest2() {
        JTextField[] data = {new JTextField("Peach", 20),
                                  new JTextField("Papaya", 20),
                                  new JTextField("Mango", 20)};
        JPanel panel = new JPanel(new GridLayout(3, 1));

        for (int i=0; i<data.length; i++){
            try {
                data[i].addActionListener(new ObjectActionListener("objModified",
                                                   new Object[]{this, data[i], "Field "+(i+1)+" Modified"}
                ));
                panel.add(data[i]);
            } catch (NoSuchMethodException e){
                System.out.println(e.getMessage());
            }
        }
        this.add(panel);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(700, 300);
        this.pack();
    }

    public static void main(String[] args){
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                (new MethodHandleTest2()).setVisible(true);
            }
        });
    }

    public class ObjectActionListener implements ActionListener {
        private Object[] parameters = null;
        private String methodName = null;

        public ObjectActionListener(String methodName, Object[] parameters)
                throws NoSuchMethodException, SecurityException {
            this.methodName = methodName;
            this.parameters = parameters;
        }

        private MethodHandle getMethod() throws NoSuchMethodException,
                IllegalAccessException {

            //For the objModified method, its return type is void, and it takes
            // a JTextField argument and a String argument.
            MethodType mt = MethodType.methodType(void.class, JTextField.class, String.class);

            //Get the MethodHandle: argument1 is the class where the method is located;
            // argument2 is the method name;
            //argument3 is the method type of the method signature
            MethodHandle mh = MethodHandles.lookup()
                    .findVirtual(MethodHandleTest2.class,
                            methodName,
                            mt);
            return mh;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            try {
                MethodHandle method = getMethod();
                //The invoke method is supposed to be able to take an array argument.
                //Somehow, it does not work for me in my test code.
               //So, I have to put each component of the array in the arguments.
                method.invoke(parameters[0], parameters[1], parameters[2]);
            } catch (IllegalAccessException e) {
                System.out.println(e.getMessage());
            } catch (InvocationTargetException e) {
                System.out.println(e.getMessage());
            } catch (Throwable e) {
                System.out.println(e.getMessage());
            }
        }
    }

    public void objModified(JTextField obj, String message){
            String text = obj.getText();
            System.out.println(message+": "+text);
    }
}

The code using reflection to do the same job can be found here

--------------------------------------------------------------------------------------------------------------

                        
If you have ever asked yourself these questions, this is the book for you. What is the meaning of life? Why do people suffer? What is in control of my life? Why is life the way it is? How can I stop suffering and be happy? How can I have a successful life? How can I have a life I like to have? How can I be the person I like to be? How can I be wiser and smarter? How can I have good and harmonious relations with others? Why do people meditate to achieve enlightenment? What is the true meaning of spiritual practice? Why all beings are one? Read the book free here.

No comments:

Post a Comment