在工作當中經常遇到反編譯后的jar文件,並要傳入參數了解其中的某些方法的輸出,想到Java里面的反射可以實現加載jar文件並調用其中的方法來達到自己的目的。就寫了個Demo代碼。
以下的類可以編譯生成hello.jar文件。
1 package org.lele.fatpanda; 2 3 public class Util 4 { 5 public static String myName; 6 /* 7 * 無參數,無返回值的方法。 8 */ 9 public static void getVersion() 10 { 11 System.out.println("java version: " + System.getProperty("java.version") ); 12 } 13 /* 14 *有參數,無返回值的方法。 15 */ 16 public static void setTmpName(String name) 17 { 18 myName = name; 19 System.out.println("Set Tmp Name Succeed and the name is : " + myName); 20 } 21 /* 22 * 單個參數,有返回值的方法。 23 */ 24 public static String getName(String prefix) 25 { 26 return prefix + "lele"; 27 } 28 /* 29 * 多個參數,有返回值的方法。 30 */ 31 public static String test(String i1, int i2) 32 { 33 return i1 + i2; 34 } 35 36 } 37 /* 38 * 一個生成jar文件的類文件,要使用public的訪問權限,如果在方便進行反射調用,則要將方法聲明為static。 39 */
下面的就是實現動態加載並調用的主要代碼。
1 package com.xiyoulele.wh; 2 3 import java.io.File; 4 import java.lang.reflect.Method; 5 import java.net.URL; 6 import java.net.URLClassLoader; 7 8 public class Main 9 { 10 public static void main(String[] args) 11 { 12 URL[] urls = new URL[] {}; 13 MyClassLoader classLoader = new MyClassLoader(urls, null); //自定義ClassLoader來加載jar文件 14 15 try 16 { 17 classLoader.addJar(new File("c:\\hello.jar").toURI().toURL()); //加載特定路徑的jar文件 18 Class<?> clazz = classLoader.loadClass("org.lele.fatpanda.Util"); //動態加載jar文件當中的特定類的class文件 19 20 //傳入一個參數一個返回值 21 22 Class<?>[] typeA = new Class[1]; //傳入要調用的方法的參數類型 23 typeA[0] = String.class; 24 25 Object[] objsA = new Object[1]; //傳入要調用的方法的具體參數 26 objsA[0] = new String("xiyou"); 27 28 Method method = clazz.getMethod("getName", typeA); //獲取要被調用的特定方法 getName(String xx) 29 30 String result = method.invoke(clazz, objsA).toString(); //調用方法,獲取方法的返回值。 31 32 System.out.println(result); //輸出方法 33 34 //傳入2個參數一個人返回值 35 36 Class<?>[] typesB = new Class[2]; 37 typesB[0] = String.class; 38 typesB[1] = Integer.TYPE; 39 40 Object[] ObjsB = new Object[2]; 41 ObjsB[0] = new String("ZT"); 42 ObjsB[1] = new Integer(520); 43 44 Method newMethod = clazz.getMethod("test", typesB); 45 String res = newMethod.invoke(clazz.newInstance(), ObjsB).toString(); 46 47 System.out.println(res); 48 49 //有傳入的參數,沒有返回值 50 Class<?>[] typesC = new Class[1]; 51 typesC[0] = String.class; 52 53 Object[] objsC = new Object[1]; 54 objsC[0] = new String("xiyoulele"); 55 56 Method methodC = clazz.getMethod("setTmpName", typesC); 57 methodC.invoke(clazz.newInstance(), objsC); 58 59 //無參數,無返回值 60 Method methodD = clazz.getDeclaredMethod("getVersion"); 61 methodD.invoke(clazz.newInstance()); 62 63 classLoader.close(); //關閉類的加載器 64 65 } catch (Exception e) 66 { 67 e.printStackTrace(); 68 } 69 } 70 //繼承URLClassLoader來實現對jar文件的加載 71 static class MyClassLoader extends URLClassLoader 72 { 73 public MyClassLoader(URL[] urls) 74 { 75 super(urls); 76 } 77 public MyClassLoader(URL[] urls, ClassLoader parent) 78 { 79 super(urls, parent); 80 } 81 public void addJar(URL url) 82 { 83 this.addURL(url); 84 } 85 } 86 } 87 /* 88 * 需求:加載jar文件,動態調用里面的方法,該方法帶有參數和返回值。 89 */
程序運行的結果: