技术开发 频道

JAVA泛型浅析


IT168技术文档】 
    JAVA泛型和C++泛型的区别: 
    Java的泛型被定义成擦除,而C++的泛型则是扩展; 
    对于C++模板,当参数类型为不同的类型时,生成的模板实例也是不同的类型,如:定义类模板 
    Template <typename T> class A : public B<T>; 
    当实例化模板时 
        A<int> a; 
        A<std::string> b; 
    这里的a和b是两种不同的类型的实例; 
    Java则不是这样的,如泛化List<E>,分别用Integer和String来实例化, 
        List<Integer> l; 
        List<String> s; 
    通过反射机制看l和s的class,他们都是List!所有的参数类型都被编译器擦除了! 
    这样造成的结果是以往用C++模板可以实现某种契约(contract )的功能在Java中变得很另类了,举一个例子: 
    C++代码:
Template <typename T > class A{ Private: T x; Public: Void func(){ int ret = x.foo(12); } }
    上面这段代码在C++中经常能够看到,它暗中就设定了一个契约:凡是能否实例化这个模板的类型T,其必须具有一个公共的函数foo,这个函数返回整数,并且接受一个整数做为参数。 
    Java的代码:
public class A<E>{ private E e; public void func(){ int ret = e.foo(12); //编译错误啊… } }
     编译器给出的错误原因是foo函数对于类型中E是未定义的!!造成这样的问题的原因有两个: 
    1、 C++的编译器直到模板被使用(实例化)的时候才去编译模板,如果你不去使用模板C++编译器不会编译模板;而实例化的时候编译器已经能够确定具体的参数类型,所以能够检测契约是否符合;Java的编译器不是这样工作的,所以它在编译模板类型的时候不能够确定E到底有没有这个foo函数; 
    2、 类型擦除的结果;修改一下上面的程序,我们看看在func中到底能够调用什么函数,一看只能调用Object对象中的函数。所有的类型E都被擦除成Object了! 
    如果真的要想实现类似C++的契约,就必须确保参数类型E不被擦除成Object!需要如下修改代码:
public class A<E extends B>{ private E e; public void func(){ int ret = e.foo(12); } } Class B{ Public int foo(int param){…}; }
    这样虽然可以实现我们期望的形式,但是约束的程度要比C++的强很多,C++中,只要任意类型,其具有一个符合契约的函数,就可以实例化模板,而Java中,则要求所有的类型必须是给定类型的子类才可以实例化模板;
0
相关文章