泛型类型参数的边界限定:提升类型安全性和代码重用性
在Java泛型中,类型参数可以被任何类替换,但有时需要限制类型参数的类型,以确保类型安全性和代码重用性。本文将探讨如何使用边界限定来实现这一目标。
问题背景:
假设需要创建一个泛型类NumericFns
,用于存储数值并执行数学运算,例如计算倒数或小数部分。该类需要支持多种数字类型,如Integer
、Float
和Double
。直接使用泛型类型参数T
会导致编译错误,因为编译器无法识别T
是否具有doubleValue()
和intValue()
方法。
解决方案:边界限定
为了解决这个问题,可以使用边界限定来限制类型参数T
必须是Number
类或其子类。在Java中,这通过extends
关键字实现:
class NumericFns<T extends Number> {
T num;
NumericFns(T n) { num = n; }
double reciprocal() { return 1 / num.doubleValue(); }
double fraction() { return num.doubleValue() - num.intValue(); }
// ...
}
通过T extends Number
,编译器知道T
一定具有doubleValue()
和intValue()
方法,从而避免了编译错误。
示例:
class BoundsDemo {
public static void main(String args[]) {
NumericFns<Integer> iOb = new NumericFns<>(5);
System.out.println("iOb 的倒数是 " + iOb.reciprocal());
System.out.println("iOb 的小数部分是 " + iOb.fraction());
System.out.println();
NumericFns<Double> dOb = new NumericFns<>(5.25);
System.out.println("dOb 的倒数为 " + dOb.reciprocal());
System.out.println("dOb 的小数部分是 " + dOb.fraction());
// 下面这行代码将导致编译错误,因为String不是Number的子类
// NumericFns<String> strOb = new NumericFns<>("错误");
}
}
多类型参数的边界限定:
边界限定也可以应用于多个类型参数,例如Pair
类:
class Pair<T, V extends T> {
T first;
V second;
Pair(T a, V b) { first = a; second = b; }
// ...
}
在这个Pair
类中,V extends T
表示V
必须是T
的子类或T
本身。这确保了传递给Pair
构造函数的两个参数具有兼容的类型。
示例:
Pair<Integer, Integer> x = new Pair<>(1, 2); // 正确
Pair<Number, Integer> y = new Pair<>(10.4, 12); // 正确,因为Integer是Number的子类
// 下面这行代码将导致编译错误,因为String不是Number的子类
// Pair<Number, String> z = new Pair<>(10.4, "12");
总结:
边界限定是Java泛型中一个强大的特性,它可以有效地限制类型参数的类型,从而提高类型安全性和代码重用性。通过合理地使用边界限定,可以编写更健壮、更易维护的泛型代码。