泛型类
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 54 课,共 87 课。
现在你已经了解泛型为什么有用,接下来创建自己的泛型类。泛型类会在类名后面的尖括号中声明一个或多个类型参数,之后可以在整个类中使用这些参数。
class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}T 是类型参数:一个占位符,在创建实例时会被实际类型替换。你可以使用任意名称,但通常使用单个大写字母:T 表示 Type,E 表示 Element,K 表示 Key,V 表示 Value。
实例化泛型类时,你可以在尖括号中指定实际类型:
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // 不需要类型转换
Box<Integer> intBox = new Box<>();
intBox.set(42);
Integer num = intBox.get();注意右侧的 <>(菱形运算符):Java 会根据声明推断类型。对于需要处理多种类型的类,你也可以使用多个类型参数:
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<String, Integer> pair = new Pair<>("age", 25);挑战
简单让我们构建一个礼物登记系统,展示泛型类的强大功能。你将创建一个灵活的存储系统,可以存放任意类型的礼物,还会创建一个登记表,通过多个类型参数将礼物名称与详情配对。
你将把代码分成三个文件:
GiftBox.java:创建一个可以包装任意类型礼物的泛型类。你的GiftBox<T>应该有一个类型为T的私有字段item,以及一个私有字段wrapped(boolean),初始值为false。添加一个接收礼物的构造函数、一个返回礼物的getItem()方法、一个将 wrapped 设为 true 的wrap()方法,以及一个返回包装状态的isWrapped()方法。添加一个getStatus()方法,根据包装状态返回[item] (wrapped)或[item] (unwrapped)。Registry.java:创建一个带有两个类型参数的泛型类,用于将收礼人与礼物配对。你的Registry<K, V>应该有一个类型为K的私有字段recipient,以及一个类型为V的私有字段gift。添加一个接收这两个值的构造函数、getter 方法getRecipient()和getGift(),以及一个返回以下内容的getEntry()方法:[recipient] -> [gift]Main.java:让你的礼物登记系统运行起来!你将收到三个输入:收礼人的姓名(String)、礼物描述(String)和礼物价值(表示美元金额的整数)。首先,创建一个包含礼物描述的
GiftBox<String>。使用wrap()方法包装礼物,然后打印它的状态。接下来,创建一个包含礼物价值的
GiftBox<Integer>(表示礼品卡金额)。不要包装这个礼物,打印它的状态以显示它尚未包装。最后,创建一个将收礼人姓名与礼物描述配对的
Registry<String, String>,并打印登记条目。
你将依次收到三个输入:收礼人姓名、礼物描述和礼物价值(整数)。
注意,同一个 GiftBox 类可以轻松处理 String 和 Integer 类型:这就是泛型的妙处!而 Registry 类展示了多个类型参数如何让你灵活地配对任意两种类型。
亲手试试
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入
String recipientName = scanner.nextLine();
String giftDescription = scanner.nextLine();
int giftValue = scanner.nextInt();
// TODO: 创建一个包含礼物描述的 GiftBox<String>
// TODO: 使用 wrap() 方法包装它
// TODO: 使用 getStatus() 输出它的状态
// TODO: 创建一个包含礼物价值的 GiftBox<Integer>
// TODO: 不要包装这个礼物盒,输出它的状态(应显示未包装)
// TODO: 创建一个 Registry<String, String>,将收礼人和礼物描述配对
// TODO: 使用 getEntry() 输出登记条目
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器