CodeGym /課程 /JAVA 25 SELF /型別自動推斷與 Java 常數

型別自動推斷與 Java 常數

JAVA 25 SELF
等級 10 , 課堂 2
開放

1. 關鍵字 var

剛開始寫 Java 程式時,迎面而來的是嚴格的型別系統:每個變數都需要明確宣告——指定其型別。這對可靠性很有幫助,但有時候寫法會顯得冗長,讓程式碼變得負擔。為了讓生活更簡單,Java 加入了一個便利工具——型別自動推斷(var

var 讓你能寫出更短更乾淨的程式碼,同時不犧牲型別安全:你只要寫出右側的值,編譯器就會自動推斷並補上型別。

範例

var age = 23;            // 編譯器會根據 23 推斷並替換為  int age
var name = "Anna";       // 編譯器會根據 "Anna" 推斷並替換為 String name
var price = 99.99;       // 編譯器會根據 99.99 推斷並替換為  double price

為什麼會有 var

  • 可讀性:不必手動寫出很長的型別(例如 HashMap<String, List<Integer>>)。
  • 彈性:之後調整型別更容易:只要改右側初始值——左側的 var 會自動配合。
  • 現代風格:幾乎所有現代 Java 專案都會在從初始化即可清楚讀出型別的地方使用 var

什麼時候可以(也應該)使用 var

  • 當從右側能明確看出變數的型別時。
  • 當型別很明顯(var price = 100; —— 很清楚是 int)。
  • 當型別太長或太複雜時(例如 HashMap<Integer, List<Calendar>>)。

陣列範例

var numbers = new int[] { 1, 2, 3, 4 };

方法範例

var input = console.nextLine(); // input 是 String(方法回傳 String)

什麼時候不建議使用 var

如果無法從右邊很直覺地看出型別,程式碼就可能變得不清楚。若一個月後你自己都看不出來它的型別,最好就明確寫出來。

var mystery = DoSomethingVeryComplicated(); // 你是誰,mystery???

這裡最好明確指定型別:

String result = DoSomethingVeryComplicated();

黃金法則:只在不會降低可讀性的地方使用 var

var——只適用於區域變數

關鍵字 var 只適用於區域變數——也就是方法內部。不能把 var 用在:

  • 方法參數;
  • 類別欄位;
  • 常數。

var 的「底層」如何運作

  • Java 編譯器在編譯時會替換為正確的型別。
  • 編譯完成後就不會有 var 的存在。
  • 沒有效能損失:這只是給程式設計師的便利性。
var year = 2025; // 在編譯階段變成:int year = 2025;

使用 var 的常見錯誤

未初始化的變數:

var a; // 錯誤:編譯器無從推斷型別!

不明確的初始化:

var list = null; // 錯誤:無法從 null 決定型別!

用不同型別重複指派變數:

var value = 5;     // value 為 int
value = "五";      // 錯誤:value 已經是 int!

比較:明確型別 vs var

情境 明確型別 var
型別明確
int age = 42;
var age = 42;
方法回傳複雜型別
HashMap<Integer, String> dict = SomeFunc();
var dict = SomeFunc();
陣列
String[] names = ...
var names = ...
建議
在大多數現代專案中,區域變數會使用 var。至於參數、欄位、常數——請使用明確型別。

2. 關鍵字 final:宣告常數

常數是指在初始化之後其值不可再變的變數。使用常數能讓程式碼更可靠、易懂,並避免誤改重要的數值或字串。

  • 圓周率(PI = 3.14159…)
  • 使用者最大數量(MAX_USERS = 1000
  • 公司名稱(COMPANY_NAME = "CodeGym"

在 Java 中使用修飾詞 final 來宣告常數。它告訴編譯器:「第一次賦值之後——就不能再改了!」


final Tip IMYA_KONSTANTY = znachenie;
在 Java 中宣告常數的語法

語法

final int DAYS_IN_WEEK = 7;
final double PI = 3.1415926535;
final String GREETING = "你好,Java!";

重點:

  • 使用 final 的變數必須被初始化(若是類別欄位,可在建構函式中初始化或立刻指定)。
  • 試圖修改其值會導致編譯錯誤。

範例:無法修改 final 變數

final int MAX_USERS = 100;
MAX_USERS = 200; // 錯誤:不能對 final 變數重新賦值

說明:如果把上述賦值語句取消註解——專案將無法編譯。

3. static final:類別層級的常數

在 Java 中,我們常需要與特定物件無關、整個類別共用的常數。這時會使用 static + final 的組合。

為什麼是 static final

  • static —— 變數屬於類別(所有物件共用一份)。
  • final —— 值不可更改。

語法

public static final double PI = 3.1415926535;
public static final int MAX_USERS = 1000;
public static final String COMPANY_NAME = "CodeGym";

宣告位置? 通常放在類別開頭(方法之前)。

類別中的使用範例

public class MathUtils 
{
    public static final double PI = 3.1415926535;

    public static double circleLength(double radius) 
    {
        return 2 * PI * radius;
    }
}

呼叫:

double len = MathUtils.circleLength(5);
System.out.println(len); // 31.4159...

請注意: 取用常數時透過類別名稱:MathUtils.PI

4. 只有 finalstatic final 的差異

final —— 欄位在初始化後不可改,但每個物件各自擁有自己的值。

static final —— 整個類別共用單一常數,與物件無關。

實務差異範例

public class User 
{
    public final String name;                       // 每個 User 各自的名稱(final)
    public static final String COMPANY = "CodeGym"; // 所有人共用一家公司(static final)

    public User(String name) 
    {
        this.name = name;
    }
}
User u1 = new User("Vasya");
User u2 = new User("Petya");

System.out.println(u1.name);      // Vasya
System.out.println(u2.name);      // Petya
System.out.println(User.COMPANY); // CodeGym

結論: name 是個別不可變欄位,COMPANY 是共用常數。

常數命名慣例

慣例是使用全部大寫並以底線分隔的名稱(UPPER_CASE_WITH_UNDERSCORES)。

public static final int MAX_USERS = 1000;
public static final double GRAVITY = 9.81;
public static final String DEFAULT_GREETING = "Hello, world!";

建議:看到這種名稱時——不要嘗試在程式碼中修改其值:編譯器不會允許。

5. 實作:宣告與使用常數

範例:含有常數的類別

public class CircleCalculator 
{
    public static final double PI = 3.1415926535;

    public static double getLength(double radius) 
    {
        return 2 * PI * radius;
    }

    public static double getArea(double radius) 
    {
        return PI * radius * radius;
    }
}

使用方式:

public class Main 
{
    public static void main(String[] args) 
    {
        double r = 5.0;
        System.out.println("圓周長:" + CircleCalculator.getLength(r));
        System.out.println("圓面積:" + CircleCalculator.getArea(r));
    }
}

輸出結果:

圓周長:31.415926535
圓面積:78.5398163375

嘗試修改常數

CircleCalculator.PI = 3.14; // 編譯錯誤: cannot assign a value to final variable PI

6. 特性與細節

物件的常數

可以對物件參照使用 final,但這不會讓物件本身不可變!它只是不允許把該變數指向別的參照。

final StringBuilder sb = new StringBuilder("Hello");
sb = new StringBuilder("World"); // 錯誤:不能指派新的物件
sb.append(", Java!");            // 允許——修改的是物件狀態
System.out.println(sb);          // Hello, Java!

結論: final 保護的是「參照」,不是「物件」。若需要真正的不可變,請使用不可變類別(例如 StringList.of() 等)。

用常數取代「魔術數字」

不佳風格:

double area = 3.1415 * r * r; // 3.1415 是什麼?為什麼是這個數字?

良好風格:

double area = PI * r * r; // 一看就知道用的是圓周率

7. 使用常數與 var 的常見錯誤

錯誤一:嘗試修改 final 變數的值。 若變數以 final 宣告,重複賦值會導致編譯錯誤。

錯誤二:嘗試用 var 來宣告常數。 宣告常數時請一律使用明確型別,搭配 finalstatic finalvar 只用於區域變數。

錯誤三:常數命名不正確。 常數應使用全部大寫並以底線分隔。像 final int maxUsers = 100; 的寫法會降低可讀性。

錯誤四:忽略可見範圍(scope)。 在方法內宣告的常數只在該方法內可見。若要在整個類別中使用,請在類別層級宣告為 static final

錯誤五:以為 final 會讓物件不可變。 final 固定的是參照,不是物件狀態——兩者不同。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION