如何存储不同类型的数据:Java 泛型的妙用

138 阅读3分钟

想象一下,你正在开发一个数据分析工具。这个工具需要存储各种类型的数据——整数、浮点数、字符串等等。在一些场景下,还需要对特定类型进行限制,以确保数据的正确性。

如果不断地对代码进行小修改,工作量会非常大。这时候,Java 的泛型机制可以帮助你更灵活地处理这些数据类型。

Java 泛型允许我们指定类型参数的上限下限,从而控制数据类型的适用范围。这样,我们可以编写更加灵活、可重用的代码。下面详细介绍如何使用泛型,并结合实际应用示例,帮助你更好地理解这种技术。

1. Java 泛型基础:定义通用类型

通过泛型,我们可以定义可以接受任意类型参数的类、接口或方法。例如,创建一个可以存储任意类型数据的容器类 Box

public class Box<T> {
    private T value;

    public void setValue(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

这里的 <T> 就是一个类型参数,可以用任何具体的类型替代,比如 Box<Integer>Box<String>。这样,一个 Box 类就可以灵活地用于不同类型的数据。

2. 常用场景 1:泛型的上限(Upper Bound)

什么是上限?

泛型上限用于限制类型参数必须是某个类或它的子类。可以通过 extends 关键字实现上限控制。例如,一个汇总数值的函数可以这样写:

import java.util.List;

public class MathUtils {
    public static <T extends Number> double sum(List<T> numbers) {
        double total = 0.0;
        for (T number : numbers) {
            total += number.doubleValue();
        }
        return total;
    }
}

在这里,<T extends Number> 表示 T 必须是 Number 的子类,因此 sum 方法能接受 List<Integer>List<Double> 类型的参数。

实际应用

在财务系统中,sum 方法可以用来汇总商品价格或计算总资产,不论价格是整数还是小数,这都非常方便。例如:

  • 用来计算一组整数商品的总价格。
  • 计算股票交易的浮动盈亏。

3. 常用场景 2:泛型的下限(Lower Bound)

什么是下限?

泛型下限用于限制类型参数必须是某个类或它的父类。通常在希望往集合中添加数据时使用,通过 super 关键字定义。例如,向列表中添加整数:

import java.util.List;

public class CollectionUtils {
    public static void addIntegers(List<? super Integer> list) {
        list.add(10);
        list.add(20);
        list.add(30);
    }
}

在这个例子中,List<? super Integer> 表示列表可以接受 Integer 或其父类(如 NumberObject)的列表,从而允许安全地向列表中添加 Integer 类型的元素。

实际应用

假设我们有一个数据收集系统,用于收集不同类型的数值数据。我们可以创建一个 Number 类型的数据收集器,并允许向其中添加 IntegerLong 等不同类型的数据。例如:

  • 向监控系统中添加各种数据值。
  • 将不同类型的数据汇总到同一数据集合中,方便后续统计和分析。

4. 总结

  • 上限(extends):适用于只读取数据的场景。使用上限可以确保读取到的数据类型是某个特定类型或其子类,典型应用是汇总不同的数值数据。
  • 下限(super):适用于写入数据的场景。使用下限可以确保向集合中添加特定类型或其父类的元素,常用于动态添加新数据。

通过这两种泛型约束,我们可以编写出既灵活又类型安全的代码。希望这些实例能帮助你更好地理解 Java 泛型在实际项目中的应用!