Menu
CoddyTech

泛型类

本课属于 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);
challenge icon

挑战

简单

让我们构建一个礼物登记系统,展示泛型类的强大功能。你将创建一个灵活的存储系统,可以存放任意类型的礼物,还会创建一个登记表,通过多个类型参数将礼物名称与详情配对。

你将把代码分成三个文件:

  • 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() 输出登记条目
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Java 在线编译器