最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于Java利用反射實(shí)現(xiàn)動(dòng)態(tài)運(yùn)行一行或多行代碼

 更新時(shí)間:2023年04月06日 09:29:31   作者:CrazyDragon_King  
這篇文章主要介紹了關(guān)于Java利用反射實(shí)現(xiàn)動(dòng)態(tài)運(yùn)行一行或多行代碼,借鑒了別人的方法和書上的內(nèi)容,最后將題目完成了,和大家一起分享以下解決方法,需要的朋友可以參考下

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("運(yùn)行耗時(shí):"+(end-start)+"ms");
	}
	
	public static void eval(String code) throws 
	IOException, 
	ClassNotFoundException, 
	InstantiationException, 
	IllegalAccessException, 
	NoSuchMethodException, 
	SecurityException, 
	IllegalArgumentException, 
	InvocationTargetException {
		//創(chuàng)建 eval.java 文件
		File file = new File("src/Eval.java");
		//創(chuàng)建緩沖輸出流
		BufferedWriter buffer = new BufferedWriter(new FileWriter(file));
		//將 code 里面的內(nèi)容寫入 buffer 中
		buffer.write("public class Eval{\n"            //必須是 public class,否則無法訪問。
				+ "public void test(){\n"
				+ code+"\n}"
				+"\n}");
		buffer.close();
		
		File parentFile = new File(file.getParent());
		//注意這里要補(bǔ)一個(gè)分隔符,不然會(huì)出錯(cuò) File.pathSeparator
		//這可能是 src  和  src/ 表示意義的區(qū)別
		String parentPath = parentFile.getAbsolutePath()+File.separatorChar;
		
		//文件分隔符,只能在前面加,因?yàn)樗呛推脚_(tái)有關(guān)的,
		//而這里我需要使用正斜杠,在windows平臺(tái)下,默認(rèn)是反斜杠
		parentPath = parentPath.replace('\\', '/');   //反斜杠要使用轉(zhuǎn)義字符

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

代碼不多,但是用到了瘋狂Java上的不少知識(shí),比如使用 URLClassLoader 加載
字節(jié)碼文件,因?yàn)橐婚_始我是想使用 Class.forName(),但是發(fā)現(xiàn)總是提示找不到class文件,這似乎是 它的限制。然后我就想到了使用 URLClassLoader 這樣加載的話,就不會(huì)有這個(gè)限制了。瘋狂 Java 上面的例子是加載一個(gè) jar 包,我這里就是加載一個(gè)單個(gè) 字節(jié)碼文件(.class 文件)。

簡要說明以下步驟:

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

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

2.然后利用Runtime.getRuntim.exec() 調(diào)用 javac 進(jìn)行編譯,因?yàn)樵次募?是無法使用的,這是一種比較簡單的編譯文件的方式,我還見到了更為復(fù)雜的方式,但是限于水平,就采用了這種最簡單的方式了。

3.獲取字節(jié)碼文件后,就要加載這個(gè)類了,但是使用 Class.forName() 這個(gè)方法,似乎不能加載任意類,必須是項(xiàng)目里面存在的類才行,這一點(diǎn)我還沒明白,轉(zhuǎn)念又想到了 ClassLoader 似乎可以解決這個(gè)問題,就是用了 URLClassLoader ,因?yàn)樗梢詮木W(wǎng)絡(luò)或者本地其他地方加載 字節(jié)碼 文件,這一點(diǎn)非常方便。

4.加載字節(jié)碼文件以后,就進(jìn)入了反射的知識(shí)了。

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

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

Java還是很有趣的,繼續(xù)深入學(xué)習(xí),會(huì)發(fā)現(xiàn)更多有趣的知識(shí)。
下面是運(yùn)行截圖:

運(yùn)行截圖

在這里插入圖片描述

到此這篇關(guān)于關(guān)于Java利用反射實(shí)現(xiàn)動(dòng)態(tài)運(yùn)行一行或多行代碼的文章就介紹到這了,更多相關(guān)Java反射實(shí)現(xiàn)動(dòng)態(tài)運(yùn)行代碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

通海县| 荆州市| 阜阳市| 周至县| 咸阳市| 迁西县| 永康市| 龙江县| 龙里县| 博湖县| 灌南县| 邵武市| 青海省| 修武县| 商丘市| 扶沟县| 岳普湖县| 吴江市| 莲花县| 东平县| 德清县| 偏关县| 安平县| 安新县| 牡丹江市| 武汉市| 文成县| 陵川县| 疏勒县| 芦山县| 定南县| 山西省| 盐津县| 郎溪县| 塔城市| 玉溪市| 麦盖提县| 涟水县| 淄博市| 阳高县| 卢湾区|