泛型(generic)

  • 泛型是一种对编程语言逻辑上的优化,使之能够更多的支持代码复用的核心思想,使用泛型的语法,经过编译器的编译之后,会被基本语法替代,从这个层面上讲,Java的泛型是一种语法糖.
Vector<String> vector = new Vector<String>();
vector.add(new String("hello"));
String str = vector.get(0);

编译中被解释成

Vector vector = new Vector();
vector.add(new String("hello"));
String str = (String)vector.get(0);
  • C++的泛型(Template)与Java的泛型(Generic)存在区别:
    • 首先Java的泛型基于类型擦除的设计实现,正如上面的代码所描述的,Java语言的泛型采用的是擦除法实现的伪泛型,泛型信息(类型变量、参数化类型)编译之后通通被除掉了.
    • C++的泛型(模板)本质上就是一套宏指令集,当代码基于泛型实例化一个对象的时候,这个泛型中所定义的类型会创建一份基于此类型的模板的代码(指令集).
    • Java与C++不同的泛型实现的一个明显区别如:
    class GenericClass<T> {
    static int count;
    public GenericClass(int count) {
            this.count = count;
        }
    }
    
    public static void main(String[] args) {
        GenericClass<String> g1 = new GenericClass<String>(1);
        GenericClass<Integer> g2 = new GenericClass<Integer>(2);
        System.out.println(g1.count);
        System.out.println(g1.getClass() == g2.getClass());
    }
    

    从输出内容中发现,虽然定了不同类型的接收参数,但在实例化的过程中使用了相同的成员变量,说明对于Java而言,Class<T>中的泛型定义无论在使用中设置成什么,都会被Java的类型擦除机制消除掉.

    2
    true
    

    接下来看C++的实例:

    //GenericClass.h
    template<class T> class GenericClass
    {
    public:
        static int val;
        GenericClass(int v);
    };
    class Aoo //伪代码
    class Boo //伪代码
    
    //GenericClass.cpp
    #include <iostream>
    #include "GenericClass.h"
    template<typename T> int GenericClass<T>::val;
    template <class T>
    GenericClass<T>::GenericClass(int v) 
    { 
        this->val = v;
    }
    
    int main()
    {
        /* code */
        GenericClass<Aoo> *aoo1 = new GenericClass<Aoo>(1);
        GenericClass<Aoo> *aoo2 = new GenericClass<Aoo>(2);
        GenericClass<Boo> *boo1 = new GenericClass<Boo>(3);
        GenericClass<Boo> *boo2 = new GenericClass<Boo>(4);
        printf("%d\n",aoo1->val);
        printf("%d\n",aoo2->val);
        printf("%d\n",boo1->val);
        printf("%d\n",boo2->val);
        return 0;
    }
    

    控制台输出可以看出GenericClass<Aoo>和GenericClass<Boo>被分别初始化了,可以说在Java中,不管类型参数是什么,GenericClass的所有实例都是同一类型。类型参数会在运行时被抹去。而C++中,参数类型不同,实例类型也不同.

    2
    2
    4
    4
    

小结

对Java泛型的理解还是要基于其编译器的机制以及语言的设计逻辑去理解代码,Java中还有其他的语法糖,都是可以按照这个逻辑去深入了解的.