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: 四则运算实现
 * 

* Create: 2018/8/12 20:39 * * @author Yang Meng([email protected]) */ 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反射方法
 * 

* Create: 2018/8/12 20:25 * * @author Yang Meng([email protected]) */ 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 getDeclaredMethodsName(String className) { try { List 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:
 * 

* Create: 2018/8/12 20:33 * * @author Yang Meng([email protected]) */ 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编程思想 类型信息

你可能感兴趣的:(Java开发笔记,Java反射机制,字符串转换为函数)