欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(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)行一行或多行代碼,借鑒了別人的方法和書(shū)上的內(nèi)容,最后將題目完成了,和大家一起分享以下解決方法,需要的朋友可以參考下

Talk is cheap, show me the code!

先來(lái)看代碼:

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)容寫(xiě)入 buffer 中
		buffer.write("public class Eval{\n"            //必須是 public class,否則無(wú)法訪問(wèn)。
				+ "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("測(cè)試使用,查看輸出文件路徑:"+url);
		
		//需要自己編譯Java文件,產(chǎn)生 class 文件
		//下面這段代碼用于編譯文件,這是比較簡(jiǎn)單的了。
		//這個(gè)絕對(duì)路徑是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)行輸出,如果沒(méi)有輸出,代表編譯成功。否則會(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 對(duì)象
		System.out.println("執(zhí)行結(jié)束");
	}
}

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

簡(jiǎn)要說(shuō)明以下步驟:

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)容寫(xiě)入 buffer 中
	    buffer.write("public class Eval{\n"            //必須是 public class,否則無(wú)法訪問(wèn)。
				+ "public void test(){\n"
				+ code+"\n}"
				+"\n}");
		buffer.close();

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

3.獲取字節(jié)碼文件后,就要加載這個(gè)類了,但是使用 Class.forName() 這個(gè)方法,似乎不能加載任意類,必須是項(xiàng)目里面存在的類才行,這一點(diǎn)我還沒(méi)明白,轉(zhuǎn)念又想到了 ClassLoader 似乎可以解決這個(gè)問(wèn)題,就是用了 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 對(duì)象

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

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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot+Netty+WebSocket實(shí)現(xiàn)消息發(fā)送的示例代碼

    SpringBoot+Netty+WebSocket實(shí)現(xiàn)消息發(fā)送的示例代碼

    這篇文章主要介紹了SpringBoot+Netty+WebSocket實(shí)現(xiàn)消息發(fā)送的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • SpringBoot消息國(guó)際化配置實(shí)現(xiàn)過(guò)程解析

    SpringBoot消息國(guó)際化配置實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了SpringBoot消息國(guó)際化配置實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Delegate IDE build/run actions to maven 配置會(huì)影響程序運(yùn)行嗎?

    Delegate IDE build/run actions to maven 配置會(huì)影響程序運(yùn)行嗎?

    這篇文章主要介紹了Delegate IDE build/run actions to maven 配置會(huì)影響程序運(yùn)行嗎,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 如何利用反射批量修改java類某一屬性的代碼詳解

    如何利用反射批量修改java類某一屬性的代碼詳解

    這篇文章主要介紹了如何利用反射批量修改java類某一屬性,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • javaweb文件打包批量下載代碼

    javaweb文件打包批量下載代碼

    這篇文章主要為大家詳細(xì)介紹了javaweb文件打包批量下載代碼,批量下載未批改作業(yè),感興趣的小伙伴們可以參考一下
    2016-06-06
  • Javacv使用ffmpeg實(shí)現(xiàn)音視頻同步播放

    Javacv使用ffmpeg實(shí)現(xiàn)音視頻同步播放

    這篇文章主要介紹了Javacv使用ffmpeg實(shí)現(xiàn)音視頻同步播放,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • sentinel流量控制框架(目錄設(shè)置)

    sentinel流量控制框架(目錄設(shè)置)

    Sentinel?是面向分布式服務(wù)架構(gòu)的高可用流量防護(hù)組件幫助開(kāi)發(fā)者保障微服務(wù)的穩(wěn)定性,本文重點(diǎn)給大家介紹sentinel流量控制框架的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2022-03-03
  • 解決HttpServletResponse和HttpServletRequest取值的2個(gè)坑

    解決HttpServletResponse和HttpServletRequest取值的2個(gè)坑

    這篇文章主要介紹了解決HttpServletResponse和HttpServletRequest取值的2個(gè)坑問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 在IDEA里gradle配置和使用的方法步驟

    在IDEA里gradle配置和使用的方法步驟

    這篇文章主要介紹了在IDEA里gradle配置和使用的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java實(shí)現(xiàn)批量操作Excel的示例詳解

    Java實(shí)現(xiàn)批量操作Excel的示例詳解

    在操作Excel的場(chǎng)景中,通常會(huì)有一些針對(duì)Excel的批量操作,以GcExcel為例,為大家詳細(xì)介紹一下Java是如何實(shí)現(xiàn)批量操作Excel的,需要的可以參考一下
    2023-07-07

最新評(píng)論