首先,泛型不具備繼承性,但是數據具備繼承性
1.核心概念解析
泛型不具備繼承性
- 即使類型A是類型B的子類,
Generic<A>
也不是Generic<B>
的子類 - 這是Java泛型的類型安全設計,防止不安全的類型轉換
數據具備繼承性
- 泛型容器中的元素仍遵循Java繼承規則
- 可以通過通配符(
extends
/super
)在泛型中利用數據的繼承關系
import java.util.*;class Animal {void eat() {System.out.println("Animal eating");}
}class Dog extends Animal {void bark() {System.out.println("Dog barking");}
}public class GenericInheritanceDemo {public static void main(String[] args) {// 1. 泛型不具備繼承性演示List<Animal> animals = new ArrayList<>();List<Dog> dogs = new ArrayList<>();// 編譯錯誤:泛型不具備繼承性// animals = dogs; // 錯誤: 不兼容的類型// 2. 數據具備繼承性演示// 創建混合動物列表List<Animal> animalList = new ArrayList<>();animalList.add(new Dog()); // √ Dog是Animal子類animalList.add(new Cat()); // √ Cat是Animal子類}
}
2.泛型通配符詳解
泛型通配符是Java泛型中處理未知或不確定類型的重要機制,主要有三種形式:
(1). 無界通配符?<?>
表示可以接受任何類型的參數化類型。
public static void printList(List<?> list) {for (Object item : list) {System.out.print(item + " ");}System.out.println();
}// 使用示例
List<String> stringList = Arrays.asList("A", "B", "C");
List<Integer> intList = Arrays.asList(1, 2, 3);
printList(stringList); // 輸出:A B C
printList(intList); // 輸出:1 2 3
(2). 上界通配符?<? extends T>
表示參數化類型是T或其子類,用于"生產者"場景(從結構中獲取元素)。
public static double sum(List<? extends Number> list) {double sum = 0.0;for (Number num : list) {sum += num.doubleValue();}return sum;
}// 使用示例
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
System.out.println(sum(intList)); // 輸出:6.0
System.out.println(sum(doubleList)); // 輸出:6.6
(3). 下界通配符?<? super T>
表示參數化類型是T或其父類,用于"消費者"場景(向結構中添加元素)。
public static void addNumbers(List<? super Integer> list) {for (int i = 1; i <= 5; i++) {list.add(i);}
}// 使用示例
List<Object> objectList = new ArrayList<>();
addNumbers(objectList);
System.out.println(objectList); // 輸出:[1, 2, 3, 4, 5]
3.綜合示例代碼
編寫一個方法,該方法接受一個列表并檢查其中是否包含特定元素。如果包含,則返回該元素;否則,返回默認值。
import java.util.List;public class WildcardDemo {public static <T> T findElementOrDefault(List<T> list, T element, T defaultValue) {for (T item : list) {if (item.equals(element)) {return item;}}return defaultValue;}public static void main(String[] args) {List<String> stringList = List.of("Apple", "Banana", "Cherry");List<Integer> intList = List.of(1, 2, 3);String foundString = findElementOrDefault(stringList, "Banana", "Not Found");Integer foundInt = findElementOrDefault(intList, 4, -1);System.out.println("Found String: " + foundString); // 輸出:Found String: BananaSystem.out.println("Found Int: " + foundInt); // 輸出:Found Int: -1}
}
4.關鍵點解釋
泛型不具備繼承性
List<Dog>
不能賦值給List<Animal>
(編譯錯誤)- 防止將
Cat
添加到Dog
列表中破壞類型安全
數據具備繼承性
Dog
對象可以添加到List<Animal>
中(向上轉型)- 在
List<Animal>
中可以調用所有Animal
的方法
通配符連接泛型與繼承
<? extends Animal>
:接受所有Animal子類的列表<? super Animal>
:接受所有Animal父類的列表- 通配符在泛型系統中建立與繼承體系的連接
類型轉換規則
- 泛型容器內元素可以安全向上轉型
- 向下轉型需要顯式類型檢查和轉換
- 通配符在編譯時保證類型安全操作
什么時候使用<T>
,什么時候使用<?>
- 使用
<T>
當你需要:- 聲明類型變量
- 在方法或類中引用該類型
- 需要向集合中添加元素
- 使用
<?>
當你:- 只關心讀取集合中的元素
- 不需要知道具體類型
- 不需要向集合中添加元素
????????設計本質:Java泛型通過"類型擦除"實現,運行時所有泛型類型都變成Object。通配符系統是在編譯器層面建立的類型安全規則,利用繼承體系實現靈活性與類型安全的平衡。
5.PECS原則(Producer-Extends, Consumer-Super)
原則解析
- Producer-Extends: 當需要從數據結構獲取數據時使用
<? extends T>
- Consumer-Super: 當需要向數據結構存入數據時使用
<? super T>
????????本文探討了Java泛型與繼承的關系。泛型本身不具備繼承性(如List<Dog>不是List<Animal>的子類),但容器中的元素仍遵循繼承規則。通過上界通配符<? extends T>可接受T及其子類,下界通配符<? super T>可接受T及其父類。泛型方法利用類型參數<T extends Animal>可實現安全類型轉換。這些特性在編譯時確保類型安全,防止運行時錯誤,同時靈活利用繼承關系處理不同類型數據。