C++泛型 PK JAVA泛型

Java SE在5.0后增加了泛型,而C++一直支持泛型,并有强大的STL。

C++的泛型其实就是一个模板生成器,缺点是代码膨胀,而JAVA的泛型和C++采取的机制完全不同,它利用“擦除”的方式把类型参数替换为限定类型(无限定类型的替换为Object),然后再编译时插入类型安全的类型转换。

【C++ code】

template<typename T>
class Base{
public:
    virtual string GetInfo() {return "Base::GetInfo";}
};

template<typename T>
class Derived: public Base<T>
{
public:
    string GetInfo() {return "Derived::GetInfo";}
};

int _tmain(int argc, _TCHAR* argv[])
{
    Base<int> bi;
    cout<<bi.GetInfo()<<endl;
    Derived<int> di;
    Base<int> &rb = di;
    cout<<rb.GetInfo()<<endl;
    return 0;
}

C++的机制是先生成一份int版本的代码(把T替换成int),在编译那份非泛型的代码。

 

【Java code】

class Base<T>{
    String getItem(T t) { return "Base" + t; }
}

class Derived extends Base<String>{
    String getItem(String s) {return "Derived" + s; }
}

public class MyTest {
    public static void main(String[] args) {
        Derived d = new Derived();
        System.out.println(d.getItem("Derived"));   
        Base<String> bs = d;
        System.out.println(bs.getItem("Base"));
    }
}

 

Java采用擦除机制,其实代码就那么一份:

class Base{
    String getItem(Object t) { return "Base" + Object; } //因为为指定限制类型,所以用Object替换
}

对OOP了解的人马上发现,这里出现了问题,显然:

Base:   String getItem(Object t); 与

Derived:String getItem(String s); 不是重写的关系,重写要求参数表相同。

那么父类对象调用getItem()就不能产生多态了啊...Java内部采用了“桥方法”的方式来解决这个问题,类似转交函数的方式。

编译器会在子类中生成一个桥方法:

Derived: String getItem(Object t) { return getItem((String)t); } 这样就重写了父类的getItem,体现出了多态机制。

观察Derived.class 字节码可以看到有这样一部分内容:

// Method descriptor #18 ()Ljava/lang/Object;
// Stack: 1, Locals: 1
bridge synthetic java.lang.Object getItem();
  0  aload_0 [this]
  1  invokevirtual Derived.getItem() : java.lang.String [19]
  4  areturn
    Line numbers:
      [pc: 0, line: 1]

 

确实生成了桥方法。简单译作:为getItem方法合成了桥方法,调用一个重载的getItem。

Java--色彩斑斓。

原文地址:http://blog.sina.com.cn/s/blog_6c6b2acd0100q1bp.html

你可能感兴趣的:(C++泛型 PK JAVA泛型)