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 |
|---|---|---|
| 型別明確 | |
|
| 方法回傳複雜型別 | |
|
| 陣列 | |
|
2. 關鍵字 final:宣告常數
常數是指在初始化之後其值不可再變的變數。使用常數能讓程式碼更可靠、易懂,並避免誤改重要的數值或字串。
- 圓周率(PI = 3.14159…)
- 使用者最大數量(MAX_USERS = 1000)
- 公司名稱(COMPANY_NAME = "CodeGym")
在 Java 中使用修飾詞 final 來宣告常數。它告訴編譯器:「第一次賦值之後——就不能再改了!」
final Tip IMYA_KONSTANTY = znachenie;
語法
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. 只有 final 與 static 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 保護的是「參照」,不是「物件」。若需要真正的不可變,請使用不可變類別(例如 String、List.of() 等)。
用常數取代「魔術數字」
不佳風格:
double area = 3.1415 * r * r; // 3.1415 是什麼?為什麼是這個數字?
良好風格:
double area = PI * r * r; // 一看就知道用的是圓周率
7. 使用常數與 var 的常見錯誤
錯誤一:嘗試修改 final 變數的值。 若變數以 final 宣告,重複賦值會導致編譯錯誤。
錯誤二:嘗試用 var 來宣告常數。 宣告常數時請一律使用明確型別,搭配 final 或 static final。var 只用於區域變數。
錯誤三:常數命名不正確。 常數應使用全部大寫並以底線分隔。像 final int maxUsers = 100; 的寫法會降低可讀性。
錯誤四:忽略可見範圍(scope)。 在方法內宣告的常數只在該方法內可見。若要在整個類別中使用,請在類別層級宣告為 static final。
錯誤五:以為 final 會讓物件不可變。 final 固定的是參照,不是物件狀態——兩者不同。
GO TO FULL VERSION