91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java怎么利用反射實現動態運行一行或多行代碼

發布時間:2023-05-06 11:13:01 來源:億速云 閱讀:268 作者:zzz 欄目:開發技術

這篇文章主要介紹“Java怎么利用反射實現動態運行一行或多行代碼”,在日常操作中,相信很多人在Java怎么利用反射實現動態運行一行或多行代碼問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java怎么利用反射實現動態運行一行或多行代碼”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Talk is cheap, show me the code!

先來看代碼:

public class TestEval {
	public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		long start = System.currentTimeMillis();
		eval("int sum = 0; for (int i = 0; i < 1000; i++){sum += i;} System.out.println(sum);");
		long end = System.currentTimeMillis();
		System.out.println("運行耗時:"+(end-start)+"ms");
	}
	
	public static void eval(String code) throws 
	IOException, 
	ClassNotFoundException, 
	InstantiationException, 
	IllegalAccessException, 
	NoSuchMethodException, 
	SecurityException, 
	IllegalArgumentException, 
	InvocationTargetException {
		//創建 eval.java 文件
		File file = new File("src/Eval.java");
		//創建緩沖輸出流
		BufferedWriter buffer = new BufferedWriter(new FileWriter(file));
		//將 code 里面的內容寫入 buffer 中
		buffer.write("public class Eval{\n"            //必須是 public class,否則無法訪問。
				+ "public void test(){\n"
				+ code+"\n}"
				+"\n}");
		buffer.close();
		
		File parentFile = new File(file.getParent());
		//注意這里要補一個分隔符,不然會出錯 File.pathSeparator
		//這可能是 src  和  src/ 表示意義的區別
		String parentPath = parentFile.getAbsolutePath()+File.separatorChar;
		
		//文件分隔符,只能在前面加,因為它是和平臺有關的,
		//而這里我需要使用正斜杠,在windows平臺下,默認是反斜杠
		parentPath = parentPath.replace('\\', '/');   //反斜杠要使用轉義字符

		//Eval.class的位置,我的電腦上是 file:///F:/JavaProject/eval/src/
		//注意最后面的文件分隔符
		//創建一個 URL 數組
		String url = "file:///"+parentPath;  
		System.out.println("測試使用,查看輸出文件路徑:"+url);
		
		//需要自己編譯Java文件,產生 class 文件
		//下面這段代碼用于編譯文件,這是比較簡單的了。
		//這個絕對路徑是Java源文件的路徑,使用javac編譯獲取 .class文件
		Process p = Runtime.getRuntime().exec("javac -encoding utf-8 "+file.getAbsolutePath()); 
		InputStream compileError = p.getErrorStream();
		//下面javac 的編譯信息,與在命令行中使用的輸出結果一樣,只是把錯誤信息放到了控制臺進行輸出,如果沒有輸出,代表編譯成功。否則會有錯誤提示。
		byte[] b = new byte[1000];
		while (compileError.read(b) != -1) {
			System.out.println(new String(b));
		}
        compileError.close();
		
		URL[] urls = {new URL(url)};
		//以默認的 ClassLoader 作為父 ClassLoader, 創建 URLClassLoader
		URLClassLoader classLoader = new URLClassLoader(urls);
		Class<?> clazz = classLoader.loadClass("Eval");
		Object ob = clazz.newInstance();
		Method mtd = clazz.getMethod("test", new Class<?>[] {});  //使用 null 會有警告
		//執行方法!
		mtd.invoke(ob, new Object[] {});  //使用 null 會有警告
		classLoader.close();   //關閉 URLClassLoader 對象
		System.out.println("執行結束");
	}
}

代碼不多,但是用到了瘋狂Java上的不少知識,比如使用 URLClassLoader 加載
字節碼文件,因為一開始我是想使用 Class.forName(),但是發現總是提示找不到class文件,這似乎是 它的限制。然后我就想到了使用 URLClassLoader 這樣加載的話,就不會有這個限制了。瘋狂 Java 上面的例子是加載一個 jar 包,我這里就是加載一個單個 字節碼文件(.class 文件)。

簡要說明以下步驟:

1.首先將eval() 函數里面的 代碼端,利用字符串拼接放入一個方法中,在放入一個類中:

       //創建 eval.java 文件
		File file = new File("src/Eval.java");
		//創建緩沖輸出流
		BufferedWriter buffer = new BufferedWriter(new FileWriter(file));
		//將 code 里面的內容寫入 buffer 中
	    buffer.write("public class Eval{\n"            //必須是 public class,否則無法訪問。
				+ "public void test(){\n"
				+ code+"\n}"
				+"\n}");
		buffer.close();

2.然后利用Runtime.getRuntim.exec() 調用 javac 進行編譯,因為源文件 是無法使用的,這是一種比較簡單的編譯文件的方式,我還見到了更為復雜的方式,但是限于水平,就采用了這種最簡單的方式了。

3.獲取字節碼文件后,就要加載這個類了,但是使用 Class.forName() 這個方法,似乎不能加載任意類,必須是項目里面存在的類才行,這一點我還沒明白,轉念又想到了 ClassLoader 似乎可以解決這個問題,就是用了 URLClassLoader ,因為它可以從網絡或者本地其他地方加載 字節碼 文件,這一點非常方便。

4.加載字節碼文件以后,就進入了反射的知識了。

		//這里的url 是當前 字節碼文件的路徑,注意后面要帶上文件分隔符 '/'
		URL[] urls = {new URL(url)};
		//以默認的 ClassLoader 作為父 ClassLoader, 創建 URLClassLoader
		URLClassLoader classLoader = new URLClassLoader(urls);
		Class<?> clazz = classLoader.loadClass("Eval");
		Object ob = clazz.newInstance();
		Method mtd = clazz.getMethod("test", new Class<?>[] {});  //使用 null 會有警告
		//執行方法!
		mtd.invoke(ob, new Object[] {});  //使用 null 會有警告
		classLoader.close();   //關閉 URLClassLoader 對象

5.然后就可以運行了,但是不知到為什么,一開始運行特別慢,居然要 5000+ms,后來第二天中午我修改了以下以后,居然變快了。

下面是運行截圖:

Java怎么利用反射實現動態運行一行或多行代碼

Java怎么利用反射實現動態運行一行或多行代碼

到此,關于“Java怎么利用反射實現動態運行一行或多行代碼”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

尚志市| 漳州市| 信阳市| 东辽县| 晋宁县| 朝阳县| 抚松县| 武陟县| 枣庄市| 东辽县| 临夏市| 台南县| 临沧市| 彰化市| 咸阳市| 遂宁市| 滁州市| 陵川县| 长兴县| 合肥市| 阜平县| 安塞县| 闽侯县| 防城港市| 韶山市| 承德县| 白朗县| 综艺| 新安县| 威海市| 辉县市| 绩溪县| 香河县| 滦南县| 剑川县| 吉木乃县| 朔州市| 镇巴县| 郴州市| 淅川县| 库伦旗|