小论Java泛型机制

原创
2018/11/15 14:49
阅读数 149

何为泛型(Generics)

面向对象编程语言的多态特性包括:任一多态(ad hoc polymorphism,又名重载)、子类型多态(subtype polymorphism,又名覆盖)以及参数多态(parameter polymorphism,也即泛型)三种特性。泛型指的是程序语句编写时不考虑变量参数类型,或程序的设计与具体才用何种类型的变量无关,而在运行时决定参数类型的程序编写方式。

在较为高级成熟的编程语言中,泛型编程是程序语言自带的特性。比如在Python或Visual Basic中,声明变量时不需要声明变量的类型。Java 是从Java 5开始支持对类进行泛型编程的。

非泛型编程造成的问题

Java 5之前,当程序中需要设置与类型无关的变量时,只能采用Object变量。下面就是一个典型的Java 5之前的程序:

public class WeakPair {
    private final Object first;
    private final Object second;

    public WeakPair(Object first, Object second){
        this.first = first;
        this.second = second;
    }

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

    public String toString(){
        return "(" + first.toString() + "," + second.toString() + ")";
    }

}

这样的程序有如下一些问题:

  1. 其调用程序的变量需要经过强制转换才能编译。
  2. 由于变量类型错误导致的程序问题不能在编译时被发现,而需要等到程序运行时才能发现。比如,如下的代码便会在运行时报TypeError异常:
WeakPair p2 = new WeakPair("Everything", 42);
int i2 = (int) p2.getFirst();

而采用泛型编程,调用程序的变量就不需要经过强制转化了,而且调用程序变量的类型错误能在编译时就被发现。比如,若将WeakPair改成泛型类之后,其调用示例如下:

如上图,程序中不符合泛型参数的调用在netbeans中就会被加上下划线。那么,这样的泛型类或泛型方法如何书写呢?

编写泛型类

Java中泛型的书写,即在类名后加上“<>”,然后再在“<>”中声明代表类型的参数即可。该参数一般采用一个大写字母,用E(entity)、T(type)、或K-V(用于类型中有键值对的情形),以下就是Pair对的泛型类书写方式。

public class Pair<T1, T2> {
    private final T1 first;
    private final T2 second;

    /**
     * 
     * @param first
     * @param second
     */
    public Pair(T1 first, T2 second){
        this.first = first;
        this.second = second;
    }

    public T1 getFirst(){  return first; }
    public T2 getSecond(){  return second; }

    public String toString(){
        return "(" + first.toString() + "," + second.toString() + ")";
    }
}

以下为它的一个调用方式:

        Pair<Integer, String> p1 = new Pair<>(i, "Everything");
        Pair<String, Integer> p2 = new Pair("Everything", 42);
        //正确的调用
        String s1 = p1.getSecond();
        int i1 = p1.getFirst();

编写泛型函数

泛型还可以用于某一函数中,而类中的其他函数不是泛型的情况。以下是一个获取一个数组中所有元素的真子集的函数:

/*
 * @author Dr.Thomas Christy, orginally created by:
 * @author Peter Schachte <schachte@unimelb.edu.au>
 * /
 public static <T> T[][] combinations(T[] list) {
        T[][] combos = (T[][])Array.newInstance(list.getClass(),
                (int) Math.pow(2, list.length));

        for (int i = 0 ; i < combos.length ; ++i) {
            int count = 0;
            for (int j = 0 ; j < list.length ; ++j) {
                if ((i & 1<<j) != 0) ++count;
            }
            combos[i] = (T[])Array.newInstance(list.getClass().getComponentType(), count);
            count = 0;
            for (int j = 0 ; j < list.length ; ++j) {
                if ((i & 1<<j) != 0) {
                    combos[i][count] = list[j];
                    ++count;
                }
            }
        }
        return combos;
    }

参考资料:

  1. W. Savitch, Absolute Java. Pearson Addison Wesley 6th Edition, 2013.
  2. T. Christy, Unimelb COMP90041 Programming and Software Development, 2018
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部