其实我的需求是在系统中 测试用户导入的jar包,所有网上找了很多解决方案,踩过很多坑,再加上以前搞c++的,对java不是很熟,
这里特意记录下,算是基本满足需求了
使用反射获得jar包中的类、方法、参数、返回值类型
使用反射获取jar包中的类、方法、参数、以及返回类型,主要参照这篇文章
/chen7019/article/details/105708338
这里面我的TestJar.jar 里面 就一个Demo类,是这样的:
package com.baidu;public class Demo {public Demo() {}public static void main(String[] args) {}public String getInfo() {return "hello world";}public int getSum(int a, int b) {return a + b;}}
@Testpublic void test2() {String path = "E:\\Desktop\\Programmer\\JavaFile\\MyWeb\\test\\web\\WEB-INF\\lib\\";String fileName = "TestJar.jar";try {JarFile jarFile = new JarFile(path + fileName);Enumeration<JarEntry> e = jarFile.entries();JarEntry entry;while (e.hasMoreElements()) {entry = (JarEntry) e.nextElement();//if (entry.getName().indexOf("META-INF") < 0 && entry.getName().indexOf(".class") >= 0) {String classFullName = entry.getName();//去掉后缀.classString className = classFullName.substring(0, classFullName.length() - 6).replace("/", ".");System.out.println(className);Class<?> c = null;try {try {// 用className这个类来装载c,但还没有实例化c = Class.forName(className);} catch (ClassNotFoundException e1) {e1.printStackTrace();}Method[] methods = c.getMethods();for (Method method : methods) {String methodName = method.getName();System.out.println("方法名称:" + methodName);System.out.println("返回值类型" + method.getReturnType());Class<?>[] parameterTypes = method.getParameterTypes();for (Class<?> clas : parameterTypes) {// String parameterName = clas.getName();String parameterName = clas.getSimpleName();System.out.println("参数类型:" + parameterName);}System.out.println("==========================");}} catch (Exception e1) {}}}} catch (IOException e) {e.printStackTrace();}}
运行代码后的输出结果
com.baidu.Demo方法名称:main返回值类型void参数类型:String[]==========================方法名称:getSum返回值类型int参数类型:int参数类型:int==========================方法名称:getInfo返回值类型class java.lang.String==========================方法名称:wait返回值类型void参数类型:long参数类型:int==========================方法名称:wait返回值类型void==========================方法名称:wait返回值类型void参数类型:long==========================方法名称:equals返回值类型boolean参数类型:Object==========================方法名称:toString返回值类型class java.lang.String==========================方法名称:hashCode返回值类型int==========================方法名称:getClass返回值类型class java.lang.Class==========================方法名称:notify返回值类型void==========================方法名称:notifyAll返回值类型void==========================Process finished with exit code 0
如何动态实例化一个类,并运行其中的方法
//用className来状态这个c,className就是上面那个代码中的,可以理解为com.xxx.xxx(去掉了后面的.class)Class<?> c = null;c = Class.forName(className);//创建对象实例Object instance=c.newInstance();
这样还不能直接调用instance的方法,要先获取 这个类中的方法 然后再 invoke;
这里我以 TestJar.jar 里面的demo 类下的 getInfo 方法为例:
// 用className这个类来装载cc = Class.forName(className);// 实例化对象Object instance=c.newInstance();//获取实例当中的方法名为show,参数只有一个且类型为string的public方法Method method=c.getMethod("getInfo");// 如果该方法有参数,后面就跟参数类型// Method method = MyTest.getMethod("show", String.class);// //传入实例以及方法参数信息(如果有)执行这个方法Object ret = method.invoke(instance);System.out.println("运行动态装载jar包的getInfo方法,并获得输出");// 如果有返回值,可以直接打印ret获得输出System.out.println(method.invoke(instance ));
全部代码
public void test2() {String path = "E:\\Desktop\\Programmer\\JavaFile\\MyWeb\\test\\web\\WEB-INF\\lib\\";String fileName = "TestJar.jar";try {JarFile jarFile = new JarFile(path + fileName);Enumeration<JarEntry> e = jarFile.entries();JarEntry entry;while (e.hasMoreElements()) {entry = (JarEntry) e.nextElement();//if (entry.getName().indexOf("META-INF") < 0 && entry.getName().indexOf(".class") >= 0) {String classFullName = entry.getName();//去掉后缀.classString className = classFullName.substring(0, classFullName.length() - 6).replace("/", ".");System.out.println(className);Class<?> c = null;try {try {// 用className这个类来装载cc = Class.forName(className);Object instance=c.newInstance();Method method=c.getMethod("getInfo");System.out.println("运行动态装载jar包的getInfo方法,并获得输出");System.out.println(method.invoke(instance ));} catch (ClassNotFoundException e1) {e1.printStackTrace();}Method[] methods = c.getMethods();for (Method method : methods) {String methodName = method.getName();System.out.println("方法名称:" + methodName);System.out.println("返回值类型" + method.getReturnType());Class<?>[] parameterTypes = method.getParameterTypes();for (Class<?> clas : parameterTypes) {// String parameterName = clas.getName();String parameterName = clas.getSimpleName();System.out.println("参数类型:" + parameterName);}System.out.println("==========================");}} catch (Exception e1) {}}}} catch (IOException e) {e.printStackTrace();}}
输出
com.baidu.Demo运行动态装载jar包的getInfo方法,并获得输出hello world方法名称:main返回值类型void参数类型:String[]==========================方法名称:getSum返回值类型int参数类型:int参数类型:int==========================方法名称:getInfo返回值类型class java.lang.String==========================方法名称:wait返回值类型void参数类型:long参数类型:int==========================方法名称:wait返回值类型void==========================方法名称:wait返回值类型void参数类型:long==========================方法名称:equals返回值类型boolean参数类型:Object==========================方法名称:toString返回值类型class java.lang.String==========================方法名称:hashCode返回值类型int==========================方法名称:getClass返回值类型class java.lang.Class==========================方法名称:notify返回值类型void==========================方法名称:notifyAll返回值类型void==========================Process finished with exit code 0
用getSum方法也是一样:
c = Class.forName(className);Object instance=c.newInstance();Method method=c.getMethod("getSum",int.class,int.class);System.out.println("运行动态装载jar包的getSum方法,并获得输出");System.out.println(method.invoke(instance,2,3));
com.baidu.Demo运行动态装载jar包的getSum方法,并获得输出5