在缺乏eclipse和idea等IDE的工具的情況下,使用jdk自帶的javac命令編譯Java項目
當項目只有一個Java文件的時候,可以直接使用
javac 文件名.java
但是如果有多個源文件的時候, 例如項目結構如下:
com.rogueq.MainClass
package com.rogueq;
import com.rogueq.service.HelloService;
import com.rogueq.service.impl.HelloServiceImpl;
public class MainClass {
public static void main(String[] args) {
HelloService helloService = new HelloServiceImpl();
helloService.sayHello();
}
}
com.rogueq.service.HelloService
package com.rogueq.service;
public interface HelloService {
void sayHello();
}
com.rogueq.service.impl
package com.rogueq.service.impl;
import com.rogueq.service.HelloService;
public class HelloServiceImpl implements HelloService {
@Override
public void sayHello() {
System.out.println("Hello world Manual Packaging !!!!!");
}
}
此時我們可以使用命令
javac -d out com/rogueq/*.java com/rogueq/service/*.java com/rogueq/service/impl/*.java
-d 參數指定class文件的輸出目錄
以上路徑皆爲相對路徑(相對當前目錄), 也可以使用絕對路徑
上面的項目因爲文件夾少,所以我們可以手動將所有還有java文件的文件路徑寫全,但是如果一個項目很大, 手動寫則會比較耗時且容易出錯。
所以需要我們自己寫一個工具類 ManualCompile.java
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
public class ManualCompile {
private static final String USER_DIR = System.getProperty("user.dir");
private static final String FILE_SEPARATOR = System.getProperty("file.separator");
private static final String OS_NAME = System.getProperty("os.name");
public static void main(String[] args) throws IOException {
String sourcePath = USER_DIR;
if (args.length > 0) {
sourcePath = getPath(args[0]);
}
Set<String> dirs = getSourceDirs(new File(sourcePath));
String input = dirs.toString()
.replace(",", "")
.replace("[", "")
.replace("]", "");
System.out.println(input);
String output;
if (args.length >= 2) {
output = createDestDirectory(args[1]);
} else {
output = createDestDirectory("out");
}
// 打印將要執行的javac 命令
System.out.println("javac -d " + output + " " + input);
try {
// 執行javac編譯操作
Runtime.getRuntime().exec("javac -d " + output + " " + input);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Failure");
}
System.out.println("SUCCESS, The dest path is [" + output + "]");
}
// 創建class文件的存放目錄 默認路徑爲當前工作路徑下的out文件夾
private static String createDestDirectory(String args) {
String destPath = getPath(args);
File file = new File(destPath);
if (!file.exists()) {
file.mkdirs();
}
return file.getAbsolutePath();
}
// 獲取要編譯的java源文件的目錄, 並在目錄的末尾添加上了 *.java
private static Set<String> getSourceDirs(File file) {
Set<String> resultDirs = new HashSet<>();
if (file.isFile() && file.getName().endsWith(".java")) {
resultDirs.add(file.getAbsolutePath().replace(file.getName(), "*.java"));
return resultDirs;
} else if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
resultDirs.addAll(getSourceDirs(f));
}
}
return resultDirs;
}
// 根據傳入的參數獲取當前項目工作路徑
private static String getPath(String sourcePath) {
String path;
if (sourcePath == null) {
return USER_DIR;
}
path = sourcePath.trim();
if (!path.contains(":") && OS_NAME.toLowerCase().contains("windows")) {
if (path.startsWith("\\") || path.startsWith("/")) {
path = USER_DIR + path;
} else {
path = USER_DIR + FILE_SEPARATOR + path;
}
if (!(path.endsWith("\\") || path.endsWith("/"))) {
path += FILE_SEPARATOR;
}
}
if (OS_NAME.toLowerCase().contains("linux") && !path.startsWith("/")) {
path = USER_DIR + FILE_SEPARATOR + path;
}
return path.replace("\\", FILE_SEPARATOR).replace("/", FILE_SEPARATOR);
}
}
工具類功能說明如下:
當不傳入參數的時候, 將編譯當前目錄下的文件
命令: (java ManualClass)
例如: 當前目錄爲 D:/project/hello 則會編譯D:/project/hello 目錄下的所有java文件 編譯完成後的文件放置在 D:/project/hello/out文件夾中
當只傳入一個參數的時候, 將編譯該參數指定的目錄下的文件
命令:(java ManualClass D:/project/hello)
例如: 當前目錄爲 D:/project/hello 參數爲 D:/project/haha 則會編譯D:/project/haha下的所有java文件 編譯完成後的文件放置在 D:/project/hello/out文件夾中
當傳入兩參數的時候, 將編譯第一個參數指定的目錄下的文件 並把編譯完成的class文件放入第二個目錄指定的文件夾
命令:(java ManualClass D:/project/hello D:/project/hello/dest)
參數支持絕對路徑和相對路徑
例如: D:/project/haha 或 /heihei 但不支持 ../
總結:
第一個參數爲要編譯的java的文件夾或java文件 默認是當前目錄
第二參數爲編譯完成的class文件的放置文件夾 默認是當前目錄下的out文件夾(沒有會自動創建)
路徑格式支持絕對路徑和相對路徑, 但是不支持../