Java是一種先編譯后解釋的語(yǔ)言。Java編譯器將源代碼編譯成Java字節(jié)碼,而Java虛擬機(jī)則將字節(jié)碼解釋成機(jī)器語(yǔ)言。
Java的編譯有兩種方式:靜態(tài)編譯和動(dòng)態(tài)編譯。
靜態(tài)編譯是指在程序運(yùn)行前,將Java源代碼編譯成字節(jié)碼文件,這個(gè)過程叫做Java編譯。編譯過程將源代碼轉(zhuǎn)換成字節(jié)碼,然后將字節(jié)碼文件存儲(chǔ)到硬盤上。當(dāng)需要運(yùn)行程序時(shí),Java虛擬機(jī)會(huì)加載字節(jié)碼文件,并執(zhí)行其中的代碼。
//示例:Java靜態(tài)編譯 public class Test { public static void main(String[] args) { System.out.println("Hello, World!"); } } //編譯 javac Test.java //運(yùn)行 java Test
動(dòng)態(tài)編譯是指在程序運(yùn)行時(shí),將Java源代碼編譯成字節(jié)碼,然后將字節(jié)碼加載到內(nèi)存中,再執(zhí)行。
//示例:Java動(dòng)態(tài)編譯 import java.io.*; import javax.tools.*; public class Test { public static void main(String[] args) throws Exception { //設(shè)置Java文件 String fileName = "Test.java"; //讀取文件 String source = new String(Files.readAllBytes(Paths.get(fileName))); //準(zhǔn)備編譯器 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); //設(shè)置編譯任務(wù) DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromStrings(Arrays.asList(source)); JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits); //執(zhí)行編譯任務(wù) if (!task.call()) { for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) { System.err.println(diagnostic.getKind() + ": " + diagnostic.getMessage(null)); } } //執(zhí)行編譯后的代碼 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Class<?> aClass = classLoader.loadClass("Test"); aClass.getMethod("main", String[].class).invoke(null, (Object) args); } }
兩種編譯方式各有優(yōu)缺點(diǎn),具體應(yīng)該根據(jù)需求選擇使用。