java核心技术卷 之泛型方法

前面已经介绍了如何定义一个泛型类。实际上,还可以定义一个带有类型参数的简单方法。 

         class ArrayAlg { 

public static <T> T getMiddle(T... a) { 

return a[a.length / 2]; 

         这个方法是在普通类中定义的,而不是在泛型类中定义的。然而,这是一个泛型方法, 可以从尖括号和类型变量看出这一点。注意,类型变量放在修饰符(这里是public static)的后面,返回类型的前面。

泛型方法可以定义在普通类中,也可以定义在泛型类中。 

当调用一个泛型方法时,在方法名前的尖括号中放入具体的类型: 

String niddle = ArrayAlg.<String>getmiddle(“John”,“Q”,"Public"); 

         在这种情况(实际也是大多数情况)下,方法调用中可以省略<String>类型参数。编译器有足够的信息能够推断出所调用的方法。它用names的类型(即String[])与泛型类型T[] 进行匹配并推断出T 一定是String。也就是说,可以调用 

String middle = ArrayAlg.getMiddle("John", "Q”, "Public");

         几乎在大多数情况下,对于泛型方法的类型引用没有问题。偶尔,编译器也会提示错误,此时需要解译错误报告。看一看下面这个示例: 

double middle = ArrayAlg.getMiddle(3.14f 1729, 0);

         错误消息会以晦涩的方式指出(不同的编译器给出的错误消息可能有所不同):解释这句代码有两种方法,而且这两种方法都是合法的。简单地说,编译器将会自动打包参数为1个 Double和2个Integer对象,而后寻找这些类的共同超类型。事实上,找到2个这样的超类型: Number和Comparable接口,其本身也是一个泛型类型。在这种情况下,可以采取的补救措施是将所有的参数写为double值。

类型变量的限定

         有时,类或方法需要对类型变量加以约束。下面是一个典型的例子我们要计算数组中的最小元索: 

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 (s(nallest.coinpareTo(a[i]) > 0) smallest = a[i]; 

return smallest; 

}

         但是,这里有一个问题。请看一下min方法的代码内部。变量smallest类型为T,这意味着它可以是任何一个类的对象。怎么才能确信T所属的类有compareTo方法呢?

         解决这个问题的方案是将T限制为实现了Comparable接口(只含一个方法compareTo的 标准接口)的类。可以通过对类型变量T设置限定(bound)实现这一点: 

public static <T extends Coiparable> T min(T[] a)... 

         实际上Comparable接口本身就是一个泛型类。目前,我们忽略其复杂性以及编泽器产 生的警告。
         现在,泛型的min方法只能被实现了 Comparable接口的类(如String、Date等)的数组调用。由于Rectangle炎没有实现Comparable接口,所以凋用min将会产生 一个编译错误。

         —个类型变量或通配符可以存多个限定,例如: 

T extends Comparable & Serializable 

         限定类型用&分隔,而逗号用来分隔类型变最。 

         在Java的继承中,可以根据需要拥有多个接口超类型,但限定中至多有一个类。如果用一个类作为限定,它必须是限定列表中的第一个。

          在程序清单中,编写了一个泛型方法mimnax。这个方法计算泛型数组的最大值和最小值,并返回Pair<T>。

程序清单:

pair.java文件:

package pair2; /**
 * Created by IBM on 2017/10/16.
 */
/**
 * @version 1.00 2004-05-10
 * @author Cay Horstmann
 */
public class Pair<T>
{
    public Pair() { first = null; second = null; }
    public Pair(T first, T second) { this.first = first;  this.second = second; }

    public T getFirst() { return first; }
    public T getSecond() { return second; }

    public void setFirst(T newValue) { first = newValue; }
    public void setSecond(T newValue) { second = newValue; }

    private T first;
    private T second;
}
PairTest1.java文件

package pair2;
import java.util.Calendar;
import java.util.GregorianCalendar;
/**
 * Created by IBM on 2017/10/16.
 * 泛型类型
 */
public class PairTest1 {
    public static void main(String[] args)
    {
        GregorianCalendar[]birthdays={
                new GregorianCalendar(1906, Calendar.DECEMBER,9),//G,Hopper
                new GregorianCalendar(1815, Calendar.DECEMBER,10),//A,Lovelace
                new GregorianCalendar(1903, Calendar.DECEMBER,3),//J,von Neumann
                new GregorianCalendar(1910, Calendar.JULY,22)//K,Zuse
        };
        Pair<GregorianCalendar>mm=ArrayAlg.<GregorianCalendar>minmax(birthdays);
        System.out.println("min = "+mm.getFirst().getTime());
        System.out.println("max = "+mm.getSecond().getTime());
    }
}
class  ArrayAlg{
    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 (int i=0;i<a.length;i++){
            if(min.compareTo(a[i])>0)min=a[i];
            if(max.compareTo(a[i])<0)max=a[i];
        }
        return new Pair<>(min,max);
    }
}

运行结果:


猜你喜欢

转载自blog.csdn.net/u014572215/article/details/78247688