Java反射机制-字符串转换函数

介绍

实际开发中经常用到将字符串转换为函数,以实现class的插件式操作,即调用时不绑定class的具体方法,运行时才绑定。在python中可以通过getattr()实现字符串和函数的转换。Java是通过反射机制来实现,通过getMethod()获取指定类的method,利用method.invoke()方法实现方法的执行获取结果。

反射机制

编译时不获取.class文件(或者获取不到.class文件),运行时才打开和检查.class文件。

Java反射常用的方法有

  • getFields() 获取定义的成员变量,包括父类的成员变量
  • getMethods() 获取全部的方法,包括父类的方法
  • getAnnotations() 获取注解,包括父类的注解
  • Method的invoke()方法
  • getDeclaredMethods() 获取声明的方法
  • getDeclaredField() 获取声明的成员变量
  • getDeclaredAnnotations() 获取注解

字符串转换为函数

具体操作类

接下来我们利用Java的反射机制实现字符串和函数的转换并执行。首先定义用于实现的类,以四则运算为例,代码如下:

package com.notepad.thinkingnote.reflect;

/**
 * Description: 四则运算实现
 * <p>
 * Create:      2018/8/12 20:39
 *
 * @author Yang Meng(eyangmeng@163.com)
 */
public class CalculateNode {

    public static int add(int v1, int v2) {
        return v1 + v2;
    }

    public static int minus(int v1, int v2) {
        return v1 - v2;
    }
}

反射类

定义一个反射类,封装一些方便使用的方法。如根据类名和方法名获取对应的方法。

package com.notepad.thinkingnote.reflect;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Description: Java反射方法
 * <p>
 * Create:      2018/8/12 20:25
 *
 * @author Yang Meng(eyangmeng@163.com)
 */
public class ReflectNote {

    public static List getMethods(String className) {
        try {
            Class<?> c = Class.forName(className);
            Method [] methods = c.getMethods();
            for (Method m : methods) {
                System.out.println(m.getName());
            }
            return Arrays.asList(methods);
        } catch (ClassNotFoundException e) {
            LOG.warn("can not find class: {}", className);
            return null;
        }
    }

    public static List<String> getDeclaredMethodsName(String className) {
        try {
            List<String> methodNames = new ArrayList<>();
            Class<?> c = Class.forName(className);
            Method [] methods = c.getDeclaredMethods();
            for (Method m : methods) {
                methodNames.add(m.getName());
            }
            return methodNames;
        } catch (ClassNotFoundException e) {
            LOG.warn("can not find class: {}", className);
            return null;
        }
    }

    /**
     * 根据类名和方法名获取对应的方法
     *
     * @param name 类名
     * @param method 方法名
     * @return a Method, null 找不到
     */
    public static Method getMethod(String name, String method) {
        try {
            Class<?> c = Class.forName(name);
            for (Method m : c.getDeclaredMethods()) {
                if (m.getName().equals(method)) {
                    return m;
                }
            }
            return null;
        } catch (ClassNotFoundException e) {
            LOG.warn("can not find class: {}", name);
            return null;
        }
    }

    /**
     * 根据类名和方法名获取对应的方法
     *
     * @param cls 类
     * @param method 方法名
     * @return a Method, null 找不到
     */
    public static Method getMethod(Class<?> cls, String method) {
        for (Method m : cls.getDeclaredMethods()) {
            if (m.getName().equals(method)) {
                return m;
            }
        }
        return null;
    }

    private static final Logger LOG = LoggerFactory.getLogger(ReflectNote.class);
}

测试

字符串转换为函数的示例见 单测3:testReflect()

package com.notepad.thinkingnote.reflect;

import org.junit.Assert;
import org.junit.Test;

import java.lang.reflect.Method;

/**
 * Description:
 * <p>
 * Create:      2018/8/12 20:33
 *
 * @author Yang Meng(eyangmeng@163.com)
 */
public class ReflectNoteTest {

    @Test
    public void testGetMethods() throws Exception {
        String name = "com.notepad.thinkingnote.reflect.CalculateNode";
        System.out.println(ReflectNote.getMethods(name));
    }

    @Test
    public void testGetDeclaredMethod() throws Exception {
        String name = "com.notepad.thinkingnote.reflect.CalculateNode";
        System.out.println(ReflectNote.getDeclaredMethodsName(name));
    }

    /**
     * 字符串转换为函数并执行
     * 
     * @throws Exception 处理异常
     */
    @Test
    public void testReflect() throws Exception {
        String name = "com.notepad.thinkingnote.reflect.CalculateNode";
        String v1 = "20";
        String v2 = "10";

        // add
        String methodName = "add";
        Method m = ReflectNote.getMethod(name, methodName);
        assert m != null;
        Assert.assertEquals(m.getName(), methodName);
        System.out.println(m);
        int v = (int)m.invoke(CalculateNode.class, Integer.valueOf(v1), Integer.valueOf(v2));
        System.out.println(String.format("%s %s %s = %s", v1, methodName, v2, v));

        // 直接获取方法
        Method method = CalculateNode.class.getDeclaredMethod(methodName, int.class, int.class);
        assert method != null;
        int value = (int)method.invoke(CalculateNode.class, Integer.valueOf(v1), Integer.valueOf(v2));
        System.out.println(String.format("direct %s %s %s = %s", v1, methodName, v2, value));

        // minus
        methodName = "minus";
        Method m2 = ReflectNote.getMethod(CalculateNode.class, methodName);
        int minusValue = (int) m2.invoke(CalculateNode.class, Integer.valueOf(v1), Integer.valueOf(v2));
        System.out.println(String.format("%s %s %s = %s", v1, methodName, v2, minusValue));
    }


}

总结

通过本文我们利用Java反射机制实现字符串和函数的转换并执行。

参数

Java编程思想 类型信息

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值