Java - 泛型

各位未來的Java法師們,大家好!今天,我們將踏上一段令人興奮的旅程,探索Java泛型的世界。如果你是編程新手,別擔心;我將成為你這次冒險中的友好導遊。所以,拿起你的虛擬魔杖(鍵盤),我們一起來深入探討吧!

Java - Generics

什麼是泛型?

想像你在一間冰淇淋店,有一個容器可以裝任何口味的冰淇淋。這就是Java中泛型的本質——它們允許你創建能夠操作不同數據類型的類、接口和方法,就像我們神奇的冰淇淋容器!

Why泛型在Java中被使用?

你可能會想,“我們為什麼需要這個神奇的容器?”我的年輕學徒們,泛型提供了多項好處:

  1. 類型安全:它們通過確保你使用正確的類型來幫助防止錯誤。
  2. 代碼重用性:你可以寫出能夠操作多種數據類型的代碼。
  3. 消除造型:再也無需冗長的類型造型!

讓我們來看一個簡單的例子:

public class MagicalContainer<T> {
private T item;

public void setItem(T item) {
this.item = item;
}

public T getItem() {
return item;
}
}

在這個例子中,T是一個類型參數。就像是說,“這個容器可以裝任何類型的項目。”我們可以像這樣使用它:

MagicalContainer<String> stringContainer = new MagicalContainer<>();
stringContainer.setItem("Hello, Generics!");
String message = stringContainer.getItem();

MagicalContainer<Integer> intContainer = new MagicalContainer<>();
intContainer.setItem(42);
int number = intContainer.getItem();

看見我們如何對不同類型使用同樣的MagicalContainer類了嗎?這就是泛型的力量!

Java泛型的類型

現在,我們已經將腳趾浸入泛型的游泳池中,來探索Java中的不同泛型類型。這就像在我們的編程法術中學習不同的咒語!

1. 泛型類

我們已經看到了一個泛型類的例子,就是我们的MagicalContainer。這裡再舉一個例子:

public class Pair<K, V> {
private K key;
private V value;

public Pair(K key, V value) {
this.key = key;
this.value = value;
}

public K getKey() { return key; }
public V getValue() { return value; }
}

這個Pair類可以存放兩個可能不同類型的項目。我們可以像這樣使用它:

Pair<String, Integer> pair = new Pair<>("年齡", 25);
System.out.println(pair.getKey() + ": " + pair.getValue());  // 輸出:年齡: 25

2. 泛型方法

我們還可以在非泛型類中擁有泛型方法。這就像擁有一種神奇的咒語,可以對任何成分都有效!

public class MagicTricks {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
}

我們可以使用這個方法對任何類型的數組:

Integer[] intArray = {1, 2, 3, 4, 5};
Double[] doubleArray = {1.1, 2.2, 3.3, 4.4, 5.5};
String[] stringArray = {"Hello", "Generics", "World"};

MagicTricks.printArray(intArray);
MagicTricks.printArray(doubleArray);
MagicTricks.printArray(stringArray);

3. 限制類型參數

有時候,我們希望將我們的泛型限制在某些類型上。這就像說,“這個咒語只對神奇生物有效!”

public class NumberContainer<T extends Number> {
private T number;

public NumberContainer(T number) {
this.number = number;
}

public double getSquareRoot() {
return Math.sqrt(number.doubleValue());
}
}

在這個例子中,T必須是Number的子類。我們可以使用它與IntegerDouble等,但不能與String一起使用。

NumberContainer<Integer> intContainer = new NumberContainer<>(16);
System.out.println(intContainer.getSquareRoot());  // 輸出: 4.0

NumberContainer<Double> doubleContainer = new NumberContainer<>(25.0);
System.out.println(doubleContainer.getSquareRoot());  // 輸出: 5.0

// 這會導致編譯時錯誤:
// NumberContainer<String> stringContainer = new NumberContainer<>("不是數字");

Java泛型的優勢

現在我們已經探索了不同的泛型類型,來總結一下它們的優勢:

優勢 描述
類型安全 在編譯時而不是運行時捕獲類型錯誤
代碼重用性 寫一次,用於多種類型
消除造型 無需顯式造型,減少潛在錯誤
更好的性能 避免運行時類型檢查和造型
支持泛型算法 寫出能夠在不同類型的集合上工作的算法

結論

恭喜各位年輕的Java法師!你們剛剛學習了Java泛型的神奇世界。記住,就像任何強大的咒語一樣,泛型需要練習才能精通。如果一开始觉得有点棘手,別氣餒——即使是最偉大的法師也有學習的開始!

隨著你們在Java編程旅程的繼續,你會發現泛型到處都是,尤其是在處理集合和API時。它們是撰寫乾淨、可重用和類型安全代碼的重要工具。

持續練習,保持好奇心,在你意識到之前,你將會像真正的Java法師一樣施展出泛型咒語!下次見,願你的代碼沒有bug,編譯快速!

Credits: Image by storyset