CodeSprout程式萌芽

CHAPTER 01 · JAVA 11 FOUNDATIONS

Java 基礎語法

從 main 進入點開始,讀懂型別、運算、字串與陣列,掌握 Java 傳值與輸入輸出。

這一章學會
  • 編譯與執行 Java 11 的 Main.java
  • 區分基本型別、參考型別與型別轉換
  • 運用字串、陣列、運算子與 Scanner
先預測結果,再看輸出。

每個 Java 範例都是獨立的 Main.java,可用 JDK 11 編譯執行;請一次複製一個範例。題庫使用 public class Solution 中的 public static solve(...) 方法,請保留題目指定的型別與參數,使用 return 交回答案,不必另外讀取輸入或撰寫 main。

01|程式從 main 開始

Java 用 class 描述類別;類別中可宣告欄位與方法。main 是啟動程式的進入點,public static void main(String[] args) 的大小寫、參數與回傳型別都要保留。static 代表屬於類別,void 代表沒有回傳值。

將下例存成 Main.java,使用 JDK 11 的 javac 編譯,再用 java 執行。public 類別名稱必須與檔名一致;每個敘述通常以半形分號結尾,區塊使用大括號。System.out.println 會在輸出後換行,print 則不會。

JAVA 11 · Main.java程式碼
public class Main {
    public static void main(String[] args) {
        System.out.println("開始學習 Java 11");
        System.out.print("每天練習 ");
        System.out.println(10 + " 分鐘");
    }
}
預期輸出
開始學習 Java 11
每天練習 10 分鐘
TERMINAL本機操作指令
javac -encoding UTF-8 --release 11 Main.java
java Main

教材對照:PDF 第 4–12 頁

02|欄位、區域變數與有回傳值的方法

欄位寫在類別中;區域變數寫在方法或建構子中。static 欄位由類別共用,實例欄位由各物件各自持有。區域變數使用前必須先指定值,不能以 static 修飾。

方法宣告會說明回傳型別與參數。下例 total 回傳 int,因此用 return 交回計算結果;呼叫者可以接住回傳值再列印。方法只列印結果,不代表有回傳值。

JAVA 11 · Main.java程式碼
public class Main {
    static final String COURSE = "Java 11";
    static int total(int price, int quantity) {
        return price * quantity;
    }

    public static void main(String[] args) {
        int amount = total(25, 4);
        System.out.println(amount);
        System.out.println(COURSE);
    }
}
預期輸出
100
Java 11

教材對照:PDF 第 7–12、28–30 頁

03|註解、命名與存取範圍

// 是單行註解,/* ... */ 是區塊註解,/** ... */ 可供 javadoc 產生說明文件。@Override 等 annotation 是給工具或執行環境的中繼資料,與一般註解的功能不同。

類別慣用大駝峰命名,例如 StudentAccount;方法與變數慣用小駝峰,例如 getScore、totalPrice;常數慣用 MAX_SIZE。名稱區分大小寫、不能以數字開頭,也不能使用 class 等關鍵字。Java 11 不允許單獨以 _ 作為名稱。

  • private:限所在頂層類別範圍內存取,包含其中的巢狀類別。
  • 無修飾字:同一 package 可存取,這是 package-private,宣告時不寫 default。
  • protected:同套件可存取;跨套件子類別須遵守繼承與接收物件型別的限制。
  • public:公開存取;本課使用一般 classpath 專案,不涉及模組匯出的額外限制。
  • 頂層類別只能使用 public 或無存取修飾字。getter/setter 是方法命名慣例,仍應檢查資料是否合法。

教材對照:PDF 第 13–15、24–27 頁

04|package、import、classpath 與 JAR

原始檔的順序是 package 宣告、import 宣告、類別宣告。package school.demo; 定義套件名稱;import java.util.Scanner; 讓程式使用簡短類別名。import 的 * 只涵蓋指定套件內的型別,不會自動包含子套件;package 宣告不能帶 *。java.lang 中的 String、System 等型別可直接使用。

classpath 是尋找應用程式類別與 JAR 的根目錄或檔案清單。若 Main.java 第一行寫 package school.demo;,執行 javac -d out Main.java 後,須從套件根目錄以 java -cp out school.demo.Main 執行。Windows 多個 classpath 項目用分號,macOS/Linux 用冒號分隔。

JAR 可將編譯後的類別與資源包成一個檔案,META-INF/MANIFEST.MF 可記錄 Main-Class 等資訊。以下命令使用本章第一節沒有 package 的 Main.java;--main-class 會設定啟動類別。JDK 11 的標準函式庫以模組提供,不再使用舊教材中的 rt.jar/tools.jar 路徑。

TERMINAL本機操作指令
javac -encoding UTF-8 --release 11 Main.java
jar --create --file lesson.jar --main-class Main Main.class
jar --list --file lesson.jar
java -jar lesson.jar

教材對照:PDF 第 16–23、69–72 頁

05|八種基本資料型別與字面值

Java 的八種基本型別為 byte、short、int、long、float、double、char、boolean。整數字面值通常是 int,小數通常是 double;較大的整數可加 L,float 字面值要加 F。char 用單引號,String 用雙引號;boolean 只能是 true 或 false,不能把 0、1 當作布林值。

  • byte/short/int/long 分別為 8/16/32/64 位元帶正負號整數;int 範圍為 -2,147,483,648 到 2,147,483,647。
  • char 是 16 位元 UTF-16 碼元,不保證一個 char 就能表示所有 Unicode 字元;某些表情符號需要兩個碼元。
  • 欄位與新陣列元素有預設值:數值 0、boolean 為 false、參考為 null;區域變數不能直接套用這個規則。
  • 0b 開頭是二進位、0x 是十六進位、0 開頭的整數可表示八進位;數字中的底線只為方便閱讀。
JAVA 11 · Main.java程式碼
public class Main {
    public static void main(String[] args) {
        byte small = 12;
        short count = 300;
        int amount = 30_000;
        long large = 2_147_483_648L;
        float ratio = 1.5F;
        double average = 7.0 / 2;
        char grade = 'A';
        boolean ready = true;
        System.out.println(small + count + amount);
        System.out.println(large);
        System.out.println(ratio + " " + average);
        System.out.println(grade + " " + ready);
        System.out.println(0b1101 + " " + 0x2F + " " + 071);
    }
}
預期輸出
30312
2147483648
1.5 3.5
A true
13 47 57

教材對照:PDF 第 28–38 頁

06|轉型、整數除法與浮點誤差

整數除法會向零截去小數,7 / 2 是 3;要取得 3.5,需讓其中一個運算元成為浮點數。byte、short、char 的一般整數運算會先提升為 int;轉回較小型別時可能失去資料。強制轉型是接受轉換規則,不是保證結果符合原意。

int 轉 long 不會失去整數精度,但某些整數轉 float/double 可能失去低位精度,因此不能把所有自動轉型都視為完全無損。float/double 的部分十進位小數是近似值;需要精確十進位運算時,可用字串建立 BigDecimal。

JAVA 11 · Main.java程式碼
import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        System.out.println(7 / 2);
        System.out.println(7 / 2.0);
        System.out.println(-7 / 2);
        System.out.println((int) 3.9);
        System.out.println((byte) 257);
        System.out.println(0.3 + 0.3 + 0.3 == 0.9);
        BigDecimal value = new BigDecimal("0.3");
        System.out.println(value.add(value).add(value));
    }
}
預期輸出
3
3.5
-3
3
1
false
0.9

教材對照:PDF 第 35–40、55–56 頁

07|運算子、短路與先後順序

= 是指定,== 是比較。算術包含 +、-、*、/、%;比較包含 <、<=、>、>=、==、!=。&&、|| 有短路效果,&、| 用在布林值時會計算兩邊。條件 ? A : B 依條件選擇一個值。先用括號寫清楚意圖,再思考如何簡化。

  • 後置 value++ 先產生舊值,再遞增;前置 ++value 先遞增,再產生新值。避免一行修改同一變數多次。
  • 整數的 &、|、^、~ 分別做位元 AND、OR、XOR、反相;<< 左移、>> 帶符號右移、>>> 補零右移。
  • a += b 會把結果轉回 a 的型別;對 byte 等型別而言,不能完全當成 a = a + b。
  • 字串 + 由左至右組合;數值計算與文字混用時用括號保留原意。
JAVA 11 · Main.java程式碼
public class Main {
    public static void main(String[] args) {
        int value = 3;
        System.out.println(value++);
        System.out.println(++value);
        int denominator = 0;
        boolean valid = denominator != 0 && 12 / denominator > 2;
        System.out.println(valid);
        System.out.println(value >= 5 ? "達標" : "繼續練習");
        System.out.println("總數=" + 2 + 5);
        System.out.println("總數=" + (2 + 5));
        System.out.println(6 & 3);
        System.out.println(1 << 3);
    }
}
預期輸出
3
5
false
達標
總數=25
總數=7
2
8

教材對照:PDF 第 54–66 頁

08|String 的內容比較與不可變性

String 是參考型別。== 比較兩個參考是否指向同一物件;equals 比較字串內容,equalsIgnoreCase 則忽略大小寫。字面值可能共用字串池中的實例,但程式判斷文字內容仍應用 equals。字串不可變,串接會得到另一個結果,不會改掉先前字串。

JAVA 11 · Main.java程式碼
public class Main {
    public static void main(String[] args) {
        String first = new String("Java");
        String second = new String("Java");
        String original = first;
        System.out.println(first == second);
        System.out.println(first.equals(second));
        System.out.println("JAVA".equalsIgnoreCase(first));
        first = first + " 11";
        System.out.println(original);
        System.out.println(first.length());
        System.out.println(first.charAt(0));
    }
}
預期輸出
false
true
true
Java
7
J

教材對照:PDF 第 41–49 頁

09|陣列、二維陣列與複製

陣列長度建立後固定,索引從 0 到 length - 1。二維陣列其實是陣列中的陣列,各列可以長度不同。陣列取長度用 .length,字串則是 .length()。System.arraycopy 複製指定區段;Arrays.copyOf 可建立不同長度的新陣列。

JAVA 11 · Main.java程式碼
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] scores = {70, 80, 90};
        int[] copied = Arrays.copyOf(scores, 4);
        copied[0] = 100;
        int[][] rows = {{1, 2}, {3, 4, 5}};
        System.out.println(scores[0]);
        System.out.println(Arrays.toString(copied));
        System.out.println(rows.length + " " + rows[1].length);
        System.out.println(rows[1][2]);
        int[] part = new int[2];
        System.arraycopy(scores, 1, part, 0, 2);
        System.out.println(Arrays.toString(part));
    }
}
預期輸出
70
[100, 80, 90, 0]
2 3
5
[80, 90]

教材對照:PDF 第 42–53 頁

10|Java 一律傳值

方法參數取得的是值的副本。基本型別複製數值;參考型別複製參考值,因此方法可透過該參考修改同一陣列中的元素。但重新指定參數變數,不會讓呼叫端的變數改指向另一個物件。

JAVA 11 · Main.java程式碼
public class Main {
    static void change(int number, int[] values) {
        number = 99;
        values[0] = 8;
        values = new int[] {100};
    }

    public static void main(String[] args) {
        int number = 5;
        int[] values = {5};
        change(number, values);
        System.out.println(number);
        System.out.println(values[0]);
    }
}
預期輸出
5
8

教材對照:PDF 第 67–68 頁

11|Scanner 讀取資料與換行

Scanner 可從 System.in 讀取輸入,也能分析一段字串。nextInt、nextDouble、nextBoolean 讀取對應型別;next 以空白分隔取得一段文字,nextLine 則讀到該行結尾。下例使用固定字串,讓你直接執行並比對輸出。

JAVA 11 · Main.java程式碼
import java.util.Scanner;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner("18 Java 3.5\n完整的一行文字\n");
        input.useLocale(Locale.ROOT);
        int count = input.nextInt();
        String language = input.next();
        double hours = input.nextDouble();
        input.nextLine();
        String message = input.nextLine();
        System.out.println(count + " " + language + " " + hours);
        System.out.println(message);
        input.close();
    }
}
預期輸出
18 Java 3.5
完整的一行文字

教材對照:PDF 第 73–75 頁

WHEN SOMETHING GOES WRONG

遇到錯誤,先檢查這裡

編譯器找不到 Main 或出現非法字元

檢查檔名 Main.java、public class Main 是否一致,以及引號、分號、括號是否為半形。使用 UTF-8 儲存與編譯。

同樣的文字用 == 卻得到 false

== 看參考是否相同;比較文字內容要用 equals。不要依賴字串池的共用情況。

平均值少了小數或大數計算變成負數

確認除法兩邊的型別以及中間結果是否溢位,必要時先轉 double 或 long 再運算。

PAUSE AND TRY

先不要急著看別人的寫法

  1. 預測 9 / 2、9 / 2.0 與 (double)(9 / 2) 的結果。
  2. 將傳值範例最後改成 values[0] = 100,結果為何不同?
  3. 把 Scanner 第一行改成 18 Java;哪一步會讀取失敗?

先用紙筆預測,再改動範例中的數字或文字。結果與預期不同時,找出最早開始不同的那一步。

把這幾件事帶走

  • 先確認宣告型別,再推導每一步運算的型別。
  • String 內容用 equals,陣列索引先檢查長度。
  • Java 一律傳值,參考副本仍可能共用同一物件。

FROM READING TO PRACTICE

用三道免費題,練習本章觀念

先做簡單題確認語法,再把幾個步驟組合起來。三題都來自本章主題的 Java 免費題庫,難度表示需要組合的基本概念。

教材來源與 Java 11 對照

本章依據《第二部分 01 Java 基礎語法.pdf》PDF 第 4–75 頁整理,將原有觀念重新編寫為可閱讀與執行的網站教學。頁碼為 PDF 檔案頁次;舊版語法說明與已知誤植依 Java 11 修正,補充內容另有標示。

需要查閱更完整的規則時,可參考以下官方文件。