源代碼:https://gitee.com/AgentXiao/reflection
動(dòng)態(tài)編譯要點(diǎn):
1宴树、使用場(chǎng)景(在線代碼測(cè)評(píng))
2、動(dòng)態(tài)編譯的兩種方式
3晶疼、動(dòng)態(tài)運(yùn)行編譯好的文件的兩種方式
一酒贬、使用場(chǎng)景
在程序運(yùn)行過程中,需要再次編譯其他的程序翠霍。比如在線測(cè)評(píng)系統(tǒng)锭吨,要求在線對(duì)java文件進(jìn)行編譯和運(yùn)行。
二寒匙、實(shí)現(xiàn)動(dòng)態(tài)編譯
動(dòng)態(tài)編譯的實(shí)現(xiàn)有兩種做法:
1零如、通過Runtime調(diào)用javac,啟動(dòng)新的進(jìn)程去操作锄弱。
Runtime run = Runtime.getRuntime();
Process process = run.exec("javac d:/test/test.java");
2埠况、通過JavaCompiler動(dòng)態(tài)編譯。
/**
* @ClassName Demo01
* @Description 測(cè)試動(dòng)態(tài)編譯
* @Author xwd
* @Date 2018/10/21 21:42
*/
public class Demo01 {
public static void main(String[] args) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int result = compiler.run(null,null,null,"D:/test/a.java");
System.out.println(result == 0 ? "編譯成功" : "編譯失敗");
}
}
由于文件名為a.java棵癣,但是定義了public class test辕翰,這是錯(cuò)誤的,因此:
將文件名修改為test.java后編譯成功狈谊,生成了class文件喜命。
三、動(dòng)態(tài)運(yùn)行編譯好的類
1河劝、通過Runtime.getRuntime()運(yùn)行啟動(dòng)新的進(jìn)程運(yùn)行
/**
* @ClassName Demo03
* @Description 動(dòng)態(tài)運(yùn)行編譯好的類
* @Author xwd
* @Date 2018/10/22 10:44
*/
public class Demo03 {
public static void main(String[] args) throws IOException {
Runtime run = Runtime.getRuntime();
//run.exec("javac d:/test/test.java");
Process process = run.exec("java -cp d:/test/ test");
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String info = "";
while((info = br.readLine()) != null){
System.out.println(info);
}
}
}
2壁榕、通過反射運(yùn)行編譯好的類
/**
* @ClassName Demo04
* @Description 通過反射運(yùn)行編譯好的類
* @Author xwd
* @Date 2018/10/22 10:52
*/
public class Demo04 {
public static void main(String[] args) throws Exception {
runJavaClassByReflect("D:/test/","test");
}
public static void runJavaClassByReflect(String dir,String classFile) throws Exception{
try {
//通過url獲得Class類對(duì)象
URL[] urls = new URL[] {new URL("file:/"+dir)};
URLClassLoader loader = new URLClassLoader(urls);
Class c = loader.loadClass(classFile);
//調(diào)用加載類的main方法(必須使用Object轉(zhuǎn)型)
c.getMethod("main",String[].class).invoke(null,(Object)new String[]{});
} catch (Exception e) {
e.printStackTrace();
}
}
}
這里需要注意的是:
由于可變參數(shù)是JDK1.5之后才有的,因此在
c.getMethod("main",String[].class).invoke(null,(Object)new String[]{"aa","bb"});
中赎瞎,如果不加(Object)進(jìn)行強(qiáng)制轉(zhuǎn)型的話牌里,編譯器會(huì)編譯成:
.invoke(null,"aa","bb");
但是main方法的參數(shù)是字符串?dāng)?shù)組,會(huì)發(fā)生不匹配問題务甥。
因此必須使用(Object)進(jìn)行強(qiáng)制轉(zhuǎn)型牡辽,避免這個(gè)問題。