本文目录导读:

这是Java泛型通配符的完整学习指南,包含核心概念和实用案例:
通配符基础语法
// 无界通配符 List<?> list1 = new ArrayList<String>(); List<?> list2 = new ArrayList<Integer>(); // 上界通配符(只能读) List<? extends Number> list3 = new ArrayList<Integer>(); // 下界通配符(只能写) List<? super Integer> list4 = new ArrayList<Number>();
核心使用场景
无界通配符
public class UnboundedWildcard {
// 打印任意类型列表
public static void printList(List<?> list) {
for (Object element : list) {
System.out.print(element + " ");
}
System.out.println();
}
public static void main(String[] args) {
List<Integer> intList = Arrays.asList(1, 2, 3);
List<String> strList = Arrays.asList("A", "B", "C");
List<Double> dblList = Arrays.asList(1.1, 2.2);
printList(intList);
printList(strList);
printList(dblList);
}
}
上界通配符 ? extends T
public class UpperBoundedWildcard {
// 计算数字列表总和
public static double sumList(List<? extends Number> list) {
double sum = 0;
for (Number num : list) {
sum += num.doubleValue();
}
return sum;
}
// 复制列表(只读)
public static void copyList(List<? extends Number> src, List<? super Number> dest) {
for (Number num : src) {
dest.add(num);
}
}
public static void main(String[] args) {
List<Integer> ints = Arrays.asList(1, 2, 3);
System.out.println("Sum: " + sumList(ints));
List<Double> doubles = Arrays.asList(1.1, 2.2);
System.out.println("Sum: " + sumList(doubles));
}
}
下界通配符 ? super T
public class LowerBoundedWildcard {
// 向列表添加整数(只写)
public static void addIntegers(List<? super Integer> list) {
for (int i = 1; i <= 5; i++) {
list.add(i);
}
}
public static void main(String[] args) {
List<Number> numList = new ArrayList<>();
List<Object> objList = new ArrayList<>();
addIntegers(numList);
addIntegers(objList);
System.out.println("Number list: " + numList);
System.out.println("Object list: " + objList);
}
}
实用案例:动物园管理系统
// 动物类层次
class Animal {
String name;
Animal(String name) { this.name = name; }
public String toString() { return name; }
}
class Dog extends Animal {
Dog(String name) { super(name); }
void bark() { System.out.println(name + " 汪汪"); }
}
class Cat extends Animal {
Cat(String name) { super(name); }
void meow() { System.out.println(name + " 喵喵"); }
}
// 动物园类
public class Zoo {
// 1. 无界通配符 - 展示所有动物
public static void showAllAnimals(List<?> animals) {
System.out.println("=== 所有动物 ===");
for (Object animal : animals) {
System.out.println(animal);
}
}
// 2. 上界通配符 - 让动物表演(只读)
public static void performTricks(List<? extends Animal> performers) {
System.out.println("=== 表演开始 ===");
for (Animal animal : performers) {
System.out.println(animal + " 表演了一个节目");
}
}
// 3. 下界通配符 - 添加动物(只写)
public static void addDogToGroup(List<? super Dog> dogGroup) {
System.out.println("=== 添加狗狗 ===");
dogGroup.add(new Dog("小黑"));
dogGroup.add(new Dog("旺财"));
}
// 4. 生产者-消费者模式
public static <T> void copyAnimals(
List<? extends T> source, // 生产者
List<? super T> dest) { // 消费者
for (T animal : source) {
dest.add(animal);
}
}
public static void main(String[] args) {
// 准备动物列表
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog("小黑"));
dogs.add(new Dog("旺财"));
List<Cat> cats = new ArrayList<>();
cats.add(new Cat("咪咪"));
cats.add(new Cat("花花"));
// 1. 无界通配符使用
List<Animal> allAnimals = new ArrayList<>();
allAnimals.addAll(dogs);
allAnimals.addAll(cats);
showAllAnimals(allAnimals);
// 2. 上界通配符使用
performTricks(dogs); // List<Dog> -> List<? extends Animal>
performTricks(cats); // List<Cat> -> List<? extends Animal>
// 3. 下界通配符使用
List<Animal> animalGroup = new ArrayList<>();
addDogToGroup(animalGroup); // List<Animal> -> List<? super Dog>
System.out.println("动物组: " + animalGroup);
// 4. 生产者-消费者模式
List<Object> zooList = new ArrayList<>();
copyAnimals(dogs, zooList); // 复制狗狗到动物园列表
copyAnimals(cats, zooList); // 复制猫猫到动物园列表
System.out.println("Zoo列表: " + zooList);
// 5. 常见错误示例
/*
List<? extends Animal> extAnimal = new ArrayList<Dog>();
extAnimal.add(new Dog("错误")); // 编译错误!不能写入
List<? super Dog> supDog = new ArrayList<Animal>();
supDog.add(new Dog("正确")); // 可以!Dog是Dog的子类
supDog.add(new Animal("错")); // 编译错误!Animal不是Dog的子类
*/
}
}
PECS原则(Producer Extends, Consumer Super)
public class PECSExample {
// 方法1:读取数据(生产者)
public static <T> void readFrom(List<? extends T> producer) {
// 只能读取,不能写入
T item = producer.get(0);
System.out.println("读取: " + item);
}
// 方法2:写入数据(消费者)
public static <T> void writeTo(List<? super T> consumer, T item) {
// 只能写入,不能读取(读取为Object类型)
consumer.add(item);
Object obj = consumer.get(0); // 只能读取为Object
}
// 方法3:复制数据(同时使用)
public static <T> void copy(
List<? extends T> source, // 只读(生产者)
List<? super T> dest) { // 只写(消费者)
for (T item : source) {
dest.add(item);
}
}
public static void main(String[] args) {
List<Integer> ints = Arrays.asList(1, 2, 3);
List<Number> nums = new ArrayList<>();
// 正确用法
copy(ints, nums); // Integer -> Number
System.out.println("Copy结果: " + nums);
// 错误用法示例
// copy(nums, ints); // 编译错误!Number不能赋值给Integer
}
}
实际项目应用
// 比较器工具类
public class WildcardComparator {
// 比较两个集合的最大值
public static <T extends Comparable<T>> T max(
List<? extends T> list) {
if (list.isEmpty()) return null;
T max = list.get(0);
for (T item : list) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
// 排序(使用通配符使方法更灵活)
public static <T> void sort(List<T> list,
Comparator<? super T> comparator) {
list.sort(comparator);
}
}
// 使用示例
public class Demo {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(3, 1, 4, 1, 5);
// 通配符使得Comparator可以接收父类比较器
WildcardComparator.sort(nums,
(Comparator<Number>) (a, b) ->
Integer.compare(a.intValue(), b.intValue()));
System.out.println("排序后: " + nums);
System.out.println("最大值: " + WildcardComparator.max(nums));
}
}
使用原则总结
// 通配符使用速查表
public class WildcardSummary {
/*
* 1. 只读(获取数据):? extends T
* 2. 只写(添加数据):? super T
* 3. 既读又写:不使用通配符
* 4. 读写都可以但类型不重要:?(无界通配符)
*
* PECS原则:
* - Producer Extends(生产者使用extends)
* - Consumer Super(消费者使用super)
*/
// 只读方法
public void readOnly(List<? extends Number> list) {
Number n = list.get(0); // √ 正确
// list.add(1); // × 编译错误
}
// 只写方法
public void writeOnly(List<? super Integer> list) {
list.add(1); // √ 正确
Object o = list.get(0); // √ 但只能得到Object
}
// 既读又写(不使用通配符)
public <T> void readAndWrite(List<T> list, T item) {
T t = list.get(0);
list.add(item);
}
}
学习建议:
- 记住PECS原则 - 这是通配符使用的核心
- 理解编译时安全 - 通配符在编译期检查类型安全
- 多看源码 - Java集合框架大量使用通配符
- 实践验证 - 编写代码测试不同通配符的效果
通配符的主要目的是增加API的灵活性,让方法能接受更多类型的参数,同时保持类型安全。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播