系列: Angelia
java
163 行
· 更新於 2026-09-27
Demo.java
Angelia/Java/Week_6_7/code/06_generics_collections/Demo.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* 06_generics_collections 示範程式:Object、轉型、泛型、型別擦除、Collections API。
*
* 編譯與執行:
* javac *.java
* java -ea Demo
*/
public class Demo {
/** 泛型方法:對「任何型別」的 List 都能用;T 由編譯器從參數推論。 */
static <T> T firstOrDefault(List<T> list, T fallback) {
if (list.isEmpty()) {
return fallback;
}
return list.get(0);
}
/** 有界型別參數:T 必須是 Comparable<T>,才能呼叫 compareTo。 */
static <T extends Comparable<T>> T max(List<T> list) {
if (list.isEmpty()) {
throw new IllegalArgumentException("空串列沒有最大值");
}
T best = list.get(0);
for (T x : list) {
if (x.compareTo(best) > 0) {
best = x;
}
}
return best;
}
public static void main(String[] args) {
System.out.println("=== 1. Object:所有類別的共同祖先 ===");
Object x = "hello"; // String 是 Object 的子型別
Object y = 42; // 自動裝箱:int → Integer,Integer 是 Object 的子型別
System.out.println(" x = " + x + ",y = " + y);
// x.length(); // 編譯錯誤:編譯器只知道 x 是 Object,Object 沒有 length()
System.out.println("=== 2. 轉型(cast)與 ClassCastException ===");
String s = (String) x; // 向下轉型:告訴編譯器「相信我,它其實是 String」
System.out.println(" s.length() = " + s.length());
try {
Integer bad = (Integer) x; // 編譯器放行,執行期才發現不對
System.out.println(bad);
} catch (ClassCastException e) {
System.out.println(" 攔到 ClassCastException:" + e.getMessage());
}
// 安全的做法:先用 instanceof 檢查(Java 16+ 的「模式比對」還能順便宣告變數)
if (y instanceof Integer n) {
System.out.println(" y 是 Integer,加 1 = " + (n + 1));
}
System.out.println("=== 3. 泛型:型別安全,不必轉型 ===");
GuestList<String> names = new ArrayGuestList<>(); // <> 讓編譯器推論型別參數
names.add("Fabian");
names.add("Nicholas");
names.add("Fabian"); // 集合語意:不重複
// names.add(42); // 編譯錯誤!42 不是 String:錯誤在編譯期就被抓到
assert names.count() == 2;
System.out.println(" names.count() = " + names.count());
GuestList<Integer> ids = new ArrayGuestList<>();
ids.add(1001);
ids.add(1002);
assert ids.isComing(1001) && !ids.isComing(9999);
System.out.println(" ids.isComing(1001) = " + ids.isComing(1001));
System.out.println("=== 4. 型別擦除的陷阱 ===");
Object[] ok = names.coming(); // OK:執行期的陣列真的是 Object[]
System.out.println(" Object[] ok = " + Arrays.toString(ok));
try {
String[] boom = names.coming(); // 編譯通過,但執行期插入的 checkcast String[] 會失敗
System.out.println(boom.length);
} catch (ClassCastException e) {
System.out.println(" String[] boom = names.coming() → ClassCastException!");
System.out.println(" (T[] 在執行期被擦除成 Object[],這是 Java 泛型的真實限制)");
}
List<String> safe = ((ArrayGuestList<String>) names).comingList();
System.out.println(" 正解 comingList() = " + safe + "(用 List<T> 就沒有這個問題)");
System.out.println("=== 5. Collections API:List ===");
List<String> fruits = new ArrayList<>(); // 宣告用介面 List,實作用 ArrayList
fruits.add("banana");
fruits.add("apple");
fruits.add("cherry");
fruits.add("apple"); // List 允許重複、保持順序
System.out.println(" fruits = " + fruits + ",size = " + fruits.size());
System.out.println(" get(1) = " + fruits.get(1) + ",contains(cherry) = " + fruits.contains("cherry"));
Collections.sort(fruits);
System.out.println(" 排序後 = " + fruits);
fruits.remove("apple"); // 只移除第一個
System.out.println(" remove(apple) → " + fruits);
for (String f : fruits) { // for-each:走訪任何 Collection
System.out.println(" - " + f);
}
System.out.println("=== 6. Collections API:Set ===");
Set<String> guests = new TreeSet<>(); // TreeSet:自動排序、不重複
guests.add("Liam");
guests.add("Thomas");
guests.add("Alice");
guests.add("Liam"); // 重複:無效
System.out.println(" TreeSet = " + guests + "(排序)");
Set<String> hashGuests = new HashSet<>(guests); // HashSet:更快,但順序不保證
System.out.println(" HashSet contains(Alice) = " + hashGuests.contains("Alice"));
assert guests.size() == 3 && hashGuests.size() == 3;
System.out.println("=== 7. Collections API:Map ===");
Map<String, Integer> ages = new HashMap<>(); // 鍵 → 值
ages.put("Liam", 30);
ages.put("Thomas", 25);
ages.put("Liam", 31); // 同一個鍵:覆蓋舊值
System.out.println(" ages.get(Liam) = " + ages.get("Liam") + ",get(Nobody) = " + ages.get("Nobody"));
System.out.println(" getOrDefault(Nobody, -1) = " + ages.getOrDefault("Nobody", -1));
for (Map.Entry<String, Integer> e : new TreeMap<>(ages).entrySet()) { // TreeMap:依鍵排序走訪
System.out.println(" " + e.getKey() + " → " + e.getValue());
}
// 經典應用:計數
Map<Character, Integer> freq = new TreeMap<>();
for (char c : "mississippi".toCharArray()) {
freq.put(c, freq.getOrDefault(c, 0) + 1);
}
System.out.println(" 字元頻率 = " + freq);
assert freq.get('s') == 4;
System.out.println("=== 8. of() 工廠方法:不可變集合 ===");
List<Integer> nums = List.of(3, 1, 4, 1, 5);
try {
nums.add(9);
} catch (UnsupportedOperationException e) {
System.out.println(" List.of(...) 是不可變的:add 會拋出 UnsupportedOperationException");
}
List<Integer> mutable = new ArrayList<>(nums); // 要可變就複製一份
mutable.add(9);
System.out.println(" new ArrayList<>(nums) 之後 add(9) → " + mutable);
System.out.println("=== 9. 泛型方法與 record ===");
System.out.println(" firstOrDefault([], \"none\") = " + firstOrDefault(new ArrayList<String>(), "none"));
System.out.println(" max([3,1,4,1,5]) = " + max(nums));
System.out.println(" max([\"pear\",\"apple\"]) = " + max(List.of("pear", "apple")));
Pair<String, Integer> p = Pair.of("Liam", 30);
System.out.println(" p = " + p + ",p.swap() = " + p.swap());
assert p.equals(new Pair<>("Liam", 30)); // record 自動有正確的 equals
System.out.println("=== 10. 自動裝箱的陷阱:Integer 請用 equals 比較 ===");
Integer a = 127, b = 127, c = 1000, d = 1000;
System.out.println(" 127 == 127 → " + (a == b) + "(小整數被快取,碰巧相同)");
System.out.println(" 1000 == 1000 → " + (c == d) + "(不同物件!)");
System.out.println(" 1000.equals(1000) → " + c.equals(d));
System.out.println("全部完成。");
}
}
相關文章
Angelia
haskell
EN
更新於 2026-02-03
Adding.hs
Adding.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Adding.hs).
閱讀文章 →
Angelia
haskell
EN
更新於 2026-02-03
Area.hs
Area.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Area.hs).
閱讀文章 →
Angelia
haskell
EN
更新於 2026-02-03
Chess.hs
Chess.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Chess.hs).
閱讀文章 →
Angelia
haskell
EN
更新於 2026-02-03
ChessGraphics.hs
ChessGraphics.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/ChessGraphics.hs).
閱讀文章 →
Angelia
haskell
EN
更新於 2026-02-03
Examples.hs
Examples.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Examples.hs).
閱讀文章 →
Angelia
haskell
EN
更新於 2026-02-03
Fibonacci.hs
Fibonacci.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Fibonacci.hs).
閱讀文章 →