Java泛型-有界类型参数
当我们创建泛型类或者泛型方法时,类型参数可以用任何类类型替换,但是在某些情况下,我们可能希望限制可以在参数化类型中用作类型参数的类型。可以使用Java泛型中的有界类型参数来完成。
为什么Java泛型中需要有界类型参数
让我们尝试通过一个示例来了解它,当我们可能需要使用有界参数时。例如,我们有一个泛型类,该类具有对数字进行操作的方法,可能只想接受Number或者其子类的实例。
首先让我们看看如果不使用有界类型参数会发生什么。举例来说,我们将使用一个带有类average()的泛型类,该方法返回数字数组的平均值。我们已经定义了通用类,以便可以传递整数,双精度,浮点型的任何类型的数组。
public class BoundedType<T> { T[] numbers; BoundedType(T[] numbers){ this.numbers = numbers; } public double average(){ double sum = 0.0; for(int i = 0; i < numbers.length; i++){ // Compile time error here sum += numbers[i].doubleValue(); } double avg = sum/numbers.length; return avg; } }
为了计算平均值,假设我们已经编写了一个上面给出的通用类,其中使用了doubleValue()方法为数组中的每个数字获取double类型的数字。该方法适用于任何Number类型,因为doubleValue()方法位于Number类中,并且它是所有包装类的超类。但是你会在这行得到编译时错误
sum + =数字[i] .doubleValue();
尽管我们打算始终将此通用类用于数字,但编译器无法知道这一点。对于编译器,BoundedType <T>表示T以后可以用任何类型替换,因此必须有某种机制让编译器知道类型参数将限于类型Number的参数。那就是我们在Java泛型中使用Bounded参数的地方。
如何声明有界类型参数
要声明一个有界的类型参数,请列出类型参数的名称,然后列出extends关键字,再列出一个超类(上限)
<T扩展父类>
这指定T只能由父类或者任何父类的子类替换。因此,此处的父类充当上限。
有界类型参数示例
如果我们采用与上述相同的示例,则可以将Number用作type参数的上限,以消除编译时错误。有了编译器,就知道用于type参数的类型将是Number或者其任何子类。
public class BoundedType<T extends Number> { T[] numbers; BoundedType(T[] numbers){ this.numbers = numbers; } public double average(){ double sum = 0.0; for(int i = 0; i < numbers.length; i++){ // Compile time error here sum += numbers[i].doubleValue(); } double avg = sum/numbers.length; return avg; } public static void main(String[] args) { Integer[] numArr = {3,4,5}; BoundedType<Integer> obj = new BoundedType<Integer>(numArr); System.out.println("Average is: " + obj.average()); } }
Java泛型中的多个界限
类型参数也可以有多个界限。
<T扩展了A1&A2&A3>
具有多个界限的类型变量是界限中列出的所有类型的子类型。请注意,在多个边界的情况下,只有一个边界可以是一个类,而其他边界则必须是接口。如果界限之一是一类,则必须首先指定它。例如:
Class A { /* ... */ } interface B { /* ... */ } interface C { /* ... */ } class D <T extends A & B & C> { /* ... */ }
Java中带有泛型方法的有界类型参数
在上面的示例中,在类级别使用了有界参数,但是我们也可以使用具有有界类型参数的泛型方法。考虑一种情况,在这种情况下,我们有一种方法可以对大于指定元素的数组中的元素数进行计数,并且已按如下所示编写了它。
public static <T> int countElements(T[] numbers, T element) { int count = 0; for (T e : numbers) if (e > element) // compiler error ++count; return count; }
我们在这一行收到编译器错误
如果(e>元素)
因为大于运算符(>)仅适用于基本类型,例如short,int,double,long,float,byte和char。我们不能使用>运算符比较对象。
我们将必须使用由Comparable <T>接口界定的类型参数来编译代码。
public static <T extends Comparable<T>> int countElements(T[] numbers, T element) { int count = 0; for (T e : numbers) if (e.compareTo(element) > 0) // compiler error ++count; return count; }