Java 學習曲線陡峭,初學者常卡在環境變數、CLASSPATH、編譯執行、API 文件查找等基礎建置上。本文整理從 HelloWorld 到進階除錯的完整知識地圖,涵蓋環境配置、開發工具、核心語法、資料結構、I/O、網路、系統整合等實務主題,並附上常見錯誤解決方案。
- 線上:Oracle 官方 API (可切換版本)
- 離線:下載 JDK Documentation 整合 IDE (IntelliJ: Settings → Documentation → JavaDoc URLs)
- 源碼閱讀:JDK 安裝目錄
src.zip 或 IDE Ctrl+Click 進入類別定義
- 搜尋技巧:類別名、方法名、套件名、錯誤訊息關鍵字
第四階段:核心語法與觀念釐清
存取修飾詞
| 修飾詞 | 同類 | 同包 | 子類(異包) | 非子類(異包) |
private | ✅ | ❌ | ❌ | ❌ |
| (package-private) | ✅ | ✅ | ❌ | ❌ |
protected | ✅ | ✅ | ✅ | ❌ |
public | ✅ | ✅ | ✅ | ✅ |
常見觀念釐清
- throw vs throws:
throw new Exception() 拋出實例 / throws Exception 宣告方法可能拋出
- upcasting:子類型指派給父類型參考 (
Object obj = "str";),向上轉型安全、向下需強制轉型
- 常數定義:
public static final int MAX = 100; (命名全大寫底線分隔)
String 不可變:s1 + s2 產生新物件,頻繁拼接用 StringBuilder
編譯執行進階
| 需求 | 命令/技巧 |
| 編譯多檔案 | javac -d . *.java (依套件結構輸出) |
| 大量編譯 | Ant/Maven/Gradle (勿手寫腳本) |
| 無視窗執行 | javaw (Windows) / java (Linux/macOS 背景 &) |
| 執行 JAR | java -jar app.jar (需 Manifest Main-Class) |
| 調整記憶體 | java -Xms256m -Xmx1024m MainClass |
| 本地編譯 EXE | GraalVM Native Image / jpackage / Launch4j |
第五階段:資料類型轉換速查
基本型別與包裝類
// String ←→ 基本型別
int i = Integer.parseInt("123");
String s = Integer.toString(123); // 或 String.valueOf(123)
// String ←→ 16進位
int hex = Integer.decode("0xFF").intValue(); // 255
// 基本型別 ←→ byte[]
// int → byte[4] (大端序)
byte[] bytes = ByteBuffer.allocate(4).putInt(12345).array();
// byte[] → int
int val = ByteBuffer.wrap(bytes).getInt();
// 隨機整數
int random = new Random().nextInt(100); // 0-99
// 或 ThreadLocalRandom.current().nextInt(100)
日期時間處理 (現代 java.time)
// 當前時間
LocalDateTime now = LocalDateTime.now();
Instant nowUtc = Instant.now();
// 格式化
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str = now.format(fmt);
// 解析
LocalDateTime parsed = LocalDateTime.parse("2024-03-15 14:30:00", fmt);
// java.util.Date 互轉 (舊代碼相容)
Date legacy = Date.from(now.atZone(ZoneId.systemDefault()).toInstant());
LocalDateTime modern = legacy.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
// java.sql.Date (資料庫)
java.sql.Date sqlDate = java.sql.Date.valueOf(LocalDate.now());
第六階段:常用資料結構
集合框架選型指南
| 介面 | 實作 | 特性 | 適用場景 |
| List | ArrayList | 陣列、隨機存取快、插刪慢 | 預設首選、頻繁讀取 |
| LinkedList | 雙向鏈表、首尾增刪快 | 佇列/棧、頻繁首尾操作 |
| Set | HashSet | 雜湊、無序、唯一 | 去重、快速查找 |
| LinkedHashSet | 維持插入順序 | 有序去重 |
| TreeSet | 紅黑樹、自然序/比較器序 | 排序去重 |
| Map | HashMap | 雜湊、無序、Key 唯一 | 預設首選、快速查找 |
| LinkedHashMap | 維持插入/存取順序 | LRU 快取、有序映射 |
| TreeMap | 紅黑樹、Key 排序 | 排序映射 |
二維動態陣列實作
// 方案 1: List>
List> matrix = new ArrayList<>();
matrix.add(new ArrayList<>(Arrays.asList(1, 2, 3)));
matrix.add(new ArrayList<>(Arrays.asList(4, 5, 6)));
// 方案 2: Map> (稀疏/命名行)
Map> namedRows = new HashMap<>();
namedRows.put("row1", Arrays.asList(1, 2, 3));
第七階段:I/O、網路、系統整合
檔案讀寫現代寫法 (NIO.2)
// 讀取全文
String content = Files.readString(Path.of("file.txt"), StandardCharsets.UTF_8);
// 逐行處理 (Stream, 記憶體友善)
Files.lines(Path.of("big.log"))
.filter(line -> line.contains("ERROR"))
.forEach(System.out::println);
// 寫入
Files.writeString(Path.of("out.txt"), "Hello\n", StandardCharsets.UTF_8);
Files.write(Path.of("data.bin"), byteArray);
// 複製/移動/刪除
Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
Files.move(src, dest);
Files.deleteIfExists(path);
序列化物件持久化
// 寫入
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("user.dat"))) {
oos.writeObject(user);
}
// 讀取
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("user.dat"))) {
User u = (User) ois.readObject();
}
// ⚠️ 類別需實作 Serializable, 注意 serialVersionUID
網路基礎
// 設定 Proxy
System.setProperty("http.proxyHost", "proxy.company.com");
System.setProperty("http.proxyPort", "8080");
// HTTPS
System.setProperty("https.proxyHost", "proxy.company.com");
System.setProperty("https.proxyPort", "8080");
// 執行外部程式
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "dir");
Process p = pb.start();
try (BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()))) {
br.lines().forEach(System.out::println);
}
JNI 呼叫本地 DLL
- Java 宣告
native 方法
javac → javac -h . MyClass.java 產生 .h 檔
- C/C++ 實作 JNI 函數
- 編譯為共享庫 (
.dll/.so)
System.loadLibrary("mylib") 載入
常見錯誤與解決方案 Top 10
- NoClassDefFoundError / ClassNotFoundException → CLASSPATH 漏包、套件路徑錯誤、版本衝突
- NullPointerException → 未初始化、鏈式呼叫中間為 null、Optional 保護
- ArrayIndexOutOfBoundsException → 索引超出 0~length-1、for 迴圈邊界
- UnsupportedClassVersionError → 編譯版本高於執行版本 (如 JDK 17 編譯, JRE 11 執行)
- OutOfMemoryError → Heap 過小 (-Xmx)、記憶體洩漏 (靜態集合累積、未關閉資源)
- ClassCastException → 強制轉型錯誤、泛型類型擦除、instanceof 先檢查
- NumberFormatException → parseInt 字串非數字、trim() 先移除空白
- FileNotFoundException → 相對路徑錯誤、檔案不存在、權限不足
- SocketException / ConnectException → 防火牆、Port 被佔用、主機不可達、Proxy 未設
- StackOverflowError → 遞迴無終止條件、循環引用 (toString、equals)
學習路徑建議
- 入門 (1-2 週):語法、OO、集合、例外、I/O、單元測試 (JUnit)
- 進階 (1-2 月):多執行緒、JDBC、Servlet/JSP、Spring Boot、Maven/Gradle、Git
- 高階 (持續):JVM 調優、微服務、雲原生、架構設計、領域驅動設計
重點原則:多動手、多閱讀官方文件、善用 IDE 重構/除錯、建構工具自動化依賴管理。遇到問題先查 API、StackOverflow、官方教學,養成獨立解決問題能力。