当前位置:编程学习 > JAVA >>

Java和C++在细节上的差异(四)

八、泛型程序设计:

    1.    泛型类的定义,见如下代码:

 1    publicclassPair<T,U> {
 2        publicPair() { first = null; second = null; }
 3        publicPair(T first,U second) { this.first = first; this.second = second; }
 4        
 5        publicT getFirst() { returnfirst; }
 6        publicU getSecond() { returnsecond; }
 7        publicvoidsetFirst(T first) { this.first = first; }
 8        publicvoidsetSecond(U second) { this.second = second; }
 9        
10        privateT first;
11        privateU second;
12    }

    以上代码中的T,U都是泛型类Pair的类型参数。以下为C++中模板类的定义方式:

 1    template<typename T,typename U>
 2    classPair {
 3    public:
 4        Pair(T first,U second): _first(first),_second(second) {}
 5        ~Pair() {}
 6    public:
 7        T getFirst() { return_first; }
 8        U getSecond() { return_second; }
 9        voidsetFirst(T frist) { _first = first; }
10        voidsetSecond(U second) { _second = second; }
11    private:
12        T _first;
13        U _second;
14    }

    2.    泛型方法的定义,在Java中泛型方法不一定声明在泛型类中,可以声明在普通类中,见如下代码:

 1    publicclassMyFirst {
 2        publicstaticvoidmain(String[] args) throwsException { 
 3            String[] names = {"john","Q.","Public"};
 4            String middle = ArrayAlgo.<String>getMiddle(names);
 5            System.out.println(middle);
 6        } 
 7    }
 8    
 9    classArrayAlgo {
10        publicstatic<T> T getMiddle(T[] a) {
11            returna[a.length/2];
12        }
13    }

    在以上代码中可以看出getMiddle方法为静态泛型方法,类型变量位于修饰符"public static" 的后面,返回值的前面。调用的时候在方法名的前面给出了参数类型。由于Java的编译器提供类型推演的功能,既类型参数可以通过函数参数的类型进行推演,因此也可以直接调用泛型函数,如String middle = ArrayAlgo.getMiddle(names)。如果编译器无法通过函数参数的类型推演出类型参数的实际类型,这样将会导致编译错误。在C++中同样存在模板函数,也同样存在模板函数的类型推演,在这一点上主要的差异来自于函数声明的语法,见如下C++代码:

 1    classArrayAlgo {
 2    public:
 3        template<typename T>
 4        staticT getMiddle(T* a,size_t len) {
 5            returna[len/2];
 6        }
 7    };
 8    
 9    intmain()
10    {
11        intv[] = {1,2,3};
12        intret = ArrayAlgo::getMiddle(v,3);
13        printf("This value is %d.\n",ret);
14        return0;
15    }

    3.    类型参数的限定:有些泛型函数在使用类型参数变量时,经常会用到该类型的特殊方法,如在进行数组元素比较时,要求数组中的元素必须是Comparable接口的实现类,见如下代码:

 1    publicstatic<T> T min(T[] a) {
 2        if(a == null|| a.length == 0)
 3            returnnull;
 4        T smallest = a[0];
 5        for(inti = 0; i < a.length; ++i) {
 6            if(smallest.compareTo(a[i]) > 0)
 7                smallest = a[i];
 8        }
 9        returnsmallest;
10    }

    在以上代码中,数组元素的类型为T,如果该类型并未提供compareTo域方法,将会导致编译错误,如何确保类型参数确实提供了compareTo方法呢?如果T是Comparable接口的实现类,那么该方法一定会被提供,因此可以通过Java语法中提供的类型参数限定的方式来确保这一点。见如下修订代码:

 1    publicstatic<T extendsComparable> T min(T[] a) {
 2        if(a == null|| a.length == 0)
 3            returnnull;
 4        T smallest = a[0];
 5        for(inti = 0; i < a.length; ++i) {
 6            if(smallest.compareTo(a[i]) > 0)
 7                smallest = a[i];
 8        }
 9        returnsmallest;
10    }

    其中的<T extends Comparable>语法保证了类型参数必须是Comparable接口的实现类,否则将会导致编译错误。Java中可以支持多接口的限定,之间用&分隔,如<T extends Comparable & Serializable>和之前的例子一样,尽管同样都会导致编译错误,但是后者不仅会产生更为明确的编译错误信息,同样也使使用者能够更加清晰的看到该方法的使用规则。在标准C++中并未提供这样的限定,但是在C++中对该种方式有另外一种称谓,叫做"类型绑定",在Boost等开源库中通过更复杂的模板技巧模仿了该功能的实现。然而,就泛型的

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,