Java核心技术第12章(2)

12.3    泛型方法

    前面介绍了如何定义一个泛型类,实际上,还可以定义一个带有类型参数的简单方法.
class ArrayAlg
{
    public static <T> T getMiddle(T...a)
    {
        return a[a.length / 2];
    }
}
    这个方法是在普通类中定义的,而不是在泛型类中定义的.然而,这是一个 泛型方法,可以从尖括号和类型变量看出这一点.注意,类型变量放在修饰符(这里是 public static)的后面,返回类型的前面.
    泛型方法可以定义在普通类中,也可以定义在泛型类中.
    当调用一个泛型方法时,在方法名前的尖括号中放入具体的类型:
String middle = ArrayAlg.<String>getMiddle("John", "Q.", "Public");
    在这种情况下,方法调用中可以省略<String>类型参数.编译器有足够的信息能够推断出所调用的方法.它用names的类型(即String[])与泛型类型T[]进行匹配并推断出T一定是String,也就是说,可以调用
String middle = ArrayAlg.getMiddle("John", "Q.", "Public");

12.4    类型变量的限定

    有时,类或方法需要对类型变量加以约束.下面是一个典型的例子.要计算数组中的最小元素:
class ArrayAlg
{
    public static<T> T min(T[] a)   // almost correct
    {
        if (a == null || a.length == 0)
            return null;
        T smallest = a[0];
        for (int i = 1; i < a.length; i++)
        {
            if (smallest.compareTo(a[i])
                    smallest = a[i];
        }
        return smallest;
    }
}
    但是,这里有一个问题,变量smallest类型为T,这意味着它可以是任何一个类的对象,怎样才能保证T所属的类有compareTo方法呢?
    解决这个问题的方案似乎将T限制为实现了Comparable接口(只含一个方法compareTo的标准接口)的类.可以通过对类型变量T设置限定实现这一点:
public static <T extends Comparable> T min(T[] a) ...
    实际上Comparable接口本身就是一个泛型类型.
    现在,泛型的min方法只能被实现了Comparable接口的类(如String,Date等)的数组调用.由于Rectangle类没有实现Comparable接口,所有调用min将会产生一个编译错误.
    注释:在C++中不能对模板参数的类型加以限制.如果程序员用一个不适当的类型实例化一个模板,将会在模板代码中报告一个错误信息.
    在此为什么使用关键字 extends 而不是 implements?毕竟Comparable是一个接口.下面的符号:
<T extends BoundingType>
    表示T应该绑定类型的子类型(subtype),T和绑定类型可以是类,也可以是接口. 选择关键字 extends 的原因是更接近子类的概念.
    一个类型变量或通配符可以有多个限定,例如:
T extends Comparable & Serializable
    限定类型用"&"分隔,而逗号用来分隔类型变量.
    在Java的继承中,可以根据需要拥有多个接口超类型,但限定中至多有一个类.如果用一个类作为限定,它必须是限定列表中的第一个.
    pair2/PairTest2.java如下所示:
package pair2;

import java.util.Calendar;
import java.util.GregorianCalendar;

public class PairTest2
{
    public static void main(String[] args)
    {
        GregorianCalendar[] birthdays =
        {
            new GregorianCalendar(1906, Calendar.DECEMBER, 9),
            new GregorianCalendar(1815, Calendar.DECEMBER, 10),
            new GregorianCalendar(1903, Calendar.DECEMBER, 3),
            new GregorianCalendar(1910, Calendar.JUNE, 22)
        };
        Pair<GregorianCalendar> mm = ArrayAlg.minmax(birthdays);
        System.out.println("min = " + mm.getFirst().getTime());
        System.out.println("max = " + mm.getSecond().getTime());
    }
}

class ArrayAlg
{
    /**
     * Gets the minimum and maximum of an array of objects of type T
     * @param a an array of strings
     * @return a pair with the min and max value, or null if a is null or empty
     */
    public static <T extends Comparable> Pair<T> minmax(T[] a)
    {
        if (a == null || a.length == 0)
            return null;
        T min = a[0];
        T max = a[0];
        for (T element : a)
        {
            if (min.compareTo(element) > 0) min = element;
            if (max.compareTo(element) < 0) max = element;
        }
        return new Pair<>(min, max);
    }
}
    运行结果如下所示:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值