java_基础——用代码编译.java文件+加载class文件
【本文介绍】
本文不是深入理解和使用java编译器,只是在代码里编译.java文件的helloWorld。这种技术还是蛮有意思的,说不定在将来的某些只能化项目会运用到!^_^
【简单编译的流程】
【java代码】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.zjm.www.test; 2 3 import java.io.IOException; 4 5 import javax.tools.JavaCompiler; 6 import javax.tools.JavaCompiler.CompilationTask; 7 import javax.tools.StandardJavaFileManager; 8 import javax.tools.ToolProvider; 9 10 public class Test { 11 12 public static void main(String[] args) { 13 14 // 获取.java文件路径 15 String fileName = System.getProperty("user.dir")+ 16 "\\src\\com\\zjm\\www\\test\\TankTimeProxy.java"; 17 18 /** 19 * ToolProvider类:该类是为查找工具提供者提供方法,例如,编译器的提供者。) 20 * getSystemJavaCompiler:获取此平台提供的 Java™ 编程语言编译器。 21 */ 22 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 23 24 /** 25 * getStandardFileManager: 为此工具获取一个标准文件管理器实现的新实例。 26 * 参数: 27 * diagnosticListener - 用于非致命诊断信息的诊断侦听器;如果为 null,则使用编译器的默认方法来报告诊断信息 28 * locale - 格式化诊断信息时要应用的语言环境;如果为 null,则使用默认语言环境。 29 * charset - 用于解码字节的字符集;如果为 null,则使用平台默认的字符集 30 * 返回: 31 * 标准文件管理器 32 * 33 */ 34 StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null,null,null); 35 36 /** 37 * getJavaFileObjects:获取表示给定文件的文件对象。 38 * 参数: 39 * files - 文件数组 40 * 返回: 41 * 文件对象列表 42 */ 43 Iterable units = fileMgr.getJavaFileObjects(fileName); 44 45 /** 46 * getTask:使用给定组件和参数创建编译任务的 future 47 * 参数: 48 * out - 用于来自编译器的其他输出的 Writer;如果为 null,则使用 System.err 49 * fileManager - 文件管理器;如果为 null,则使用编译器的标准文件管理器 50 * diagnosticListener - 诊断侦听器;如果为 null,则使用编译器的默认方法报告诊断信息 51 * options - 编译器选项;null 表示没有选项 52 * classes - 类名称(用于注释处理),null 表示没有类名称 53 * compilationUnits - 要编译的编译单元;null 表示没有编译单元 54 * 返回: 55 * 表示编译的对象 56 */ 57 CompilationTask t = compiler.getTask(null,null,null,null,null,units);//编译任务 58 59 // 开始编译 60 t.call(); 61 62 // 关闭“java编译器” 63 try { 64 fileMgr.close(); 65 } catch (IOException e) { 66 e.printStackTrace(); 67 } 68 } 69 }
【其中的TankTimeProxy类】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.zjm.www.test; 2 3 public class TankTimeProxy { 4 5 public TankTimeProxy(){ 6 System.out.println("hello TankTimeProxy"); 7 } 8 }
注:默认编译后的class文件与该java文件在同一个文件夹下。
【加载class文件】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.zjm.www.test; 2 3 import java.net.URL; 4 import java.net.URLClassLoader; 5 6 public class Test2 { 7 8 public static void main(String[] args) throws Exception { 9 //1 去那个路劲下找这个类,默认是bin下面的classpath,因为自动编译后的class文件默认放在那里 10 URL[] urls = new URL[] {new URL("file:/"+System.getProperty("user.dir")+"/src/")}; 11 12 //2 去urls里面去找class 13 URLClassLoader ul = new URLClassLoader(urls); 14 15 //3 load哪个类,写全类名。 16 Class c = ul.loadClass("com.zjm.www.test.TankTimeProxy"); 17 18 // 打印:hello TankTimeProxy 即代表成功 19 Object o = c.newInstance(); 20 } 21 }
为了测试,我们在TankTimeProxy的构造方法中打印 "hello TankTimeProxy" ,如果加载类成功,那么当我们使用 newInstance() 方法时,该类的构造器将会被调用,从而打印"hello TankTimeProxy" , 实际中,确实打印出 "hello TankTimeProxy"。