124. Java 泛型 - 有界类型参数
1. 什么是有界类型参数?
有时候,可能希望限制泛型类型的参数,只允许某些特定类型或其子类作为类型参数。这时,有界类型参数非常有用。通过有界类型参数,可以指定类型参数的上限,限制它们只能是某个类或接口的子类或实现类。
例如,如果有一个方法专门用于处理数字类型,可能希望仅接受 Number
类或其子类的实例,而不接受任何非数字类型。通过有界类型参数,可以实现这一点。
2. 如何声明有界类型参数?
要声明有界类型参数,可以使用 extends
关键字来指定上限。请注意,这里的 extends
并不意味着继承,而是表示"扩展"或"实现"。例如,<T extends Number>
表示类型 T
只能是 Number
或其子类。
示例:有界类型参数
java
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
// 泛型方法,U 的类型必须是 Number 或其子类
public <U extends Number> void inspect(U u) {
System.out.println("T: " + t.getClass().getName());
System.out.println("U: " + u.getClass().getName());
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<>();
integerBox.set(10);
// 尝试传入非数字类型,编译失败
integerBox.inspect("some text"); // error: String 不是 Number 类型的子类
}
}
代码解析:
- 在
Box
类中,T
是一个泛型类型参数,它表示可以存储任何类型的对象。 inspect
方法接受类型参数U
,并通过extends Number
限制了U
必须是Number
或其子类(如Integer
、Double
等)。- 当尝试传递一个非数字类型(如
String
)时,编译会报错,说明类型参数U
必须符合有界类型的限制。
错误信息:
java
Box.java:21: <U>inspect(U) in Box<java.lang.Integer> cannot
be applied to (java.lang.String)
integerBox.inspect("10");
^ // 错误提示:String 不能传递给 Number 类型
1 error
这个错误是由于 inspect
方法要求 U
必须是 Number
或其子类,String
显然不符合这一要求。
3. 使用有界类型参数的实际应用
有界类型参数不仅限于限制实例化类型的范围,还可以在方法中调用边界类型(如 Number
)中定义的方法。这使得您可以在使用泛型时,仍然能够调用一些特定类型的方法。
示例:使用 Number
的有界类型参数
java
public class NaturalNumber<T extends Integer> {
private T n;
public NaturalNumber(T n) {
this.n = n;
}
public boolean isEven() {
return n.intValue() % 2 == 0;
}
// ...
}
代码解析:
NaturalNumber
类的类型参数T
必须是Integer
或其子类的实例。isEven
方法调用n.intValue()
来判断n
是否为偶数,intValue()
是Integer
类中定义的方法。
使用示例:
java
NaturalNumber<Integer> number = new NaturalNumber<>(10);
System.out.println(number.isEven()); // 输出:true
在这个例子中,T
被限制为 Integer
类型,因此 isEven
方法可以安全地调用 n.intValue()
。
4. 多个边界
有界类型参数不仅可以有一个边界,还可以指定多个边界。在这种情况下,类型参数必须是所有边界类型的子类或实现类。如果其中一个边界是类,则必须首先指定它。例如:
示例:多个边界的类型参数
java
class A { /* ... */ }
interface B { /* ... */ }
interface C { /* ... */ }
class D<T extends A & B & C> {
// T 必须是类 A 的子类,同时实现接口 B 和 C
}
代码解析:
D
类的类型参数T
必须是类A
的子类,并且必须实现接口B
和C
。&
运算符用于连接多个边界,表示T
必须符合所有边界类型的要求。
错误示例:
java
class D<T extends B & A & C> { /* ... */ } // 编译错误
如果未按照顺序指定边界,您会遇到编译错误。因为类 A
必须首先列出,而不能在后面。
5. 总结
- 有界类型参数 允许您限制泛型类型的范围,只允许某个类型或其子类型作为类型参数。
- 使用
extends
关键字,您可以为泛型类型参数设置一个上限,例如<T extends Number>
。 - 多个边界 允许类型参数同时继承多个类或实现多个接口。使用
&
运算符连接多个边界。 - 实际应用:通过有界类型参数,您可以在泛型方法中调用边界类型的方法,同时确保类型安全。
通过了解和应用有界类型参数,您可以更加精确地控制泛型类型的行为,确保代码的类型安全和灵活性。