C++“模板”和Java“泛型”
2018-01-22 14:44
239 查看
无论是C++的模板还是Java的泛型,都是想要实现:编译器识别类型。
只是两个语言实现这个目的的手段不同而已,C++使用的是“代码生成”的方式,而Java使用的是“类型擦除”的方式。
“代码生成”:编译器在编译期间识别实际传入的参数类型,生成用于该类型的代码。
“类型擦除”:编译器在编译期间将实际类型擦除,将每个类型都视为Object类型。
例如,假设有一下java 代码:
[java] view plain copy print?Vector<String> vector = new Vector<String>();
vector.add(new String(“hello”));
String str = vector.get(0);
编译时,上面的代码会被改写为:
[java] view plain copy print?Vector vector = new Vector();
vector.add(new String(“hello”));
String str = (String)vector.get(0);
有了Java泛型,我们可以做的事情也并没有真正改变多少;它只是让代码变得漂亮些。鉴于此,Java泛型有时也被成为”语法糖“。
这点跟C++的模板截然不同。
在C++中,模板本质上就是一套宏指令集,只是换了个名头,编译器会针对每种类型创建一份模板代码的副本。
有个证据可以证明这一点:MyClass<Foo>不会与MyClass<Bar>共享静态变量。然而,两个MyClass<Foo>实例则会共享静态变量。
[cpp] view plain copy print?/* * MyClass.cpp * * Created on: 2015?7?24? * Author: nanzhou */ template<class T> class MyClass { public: static int val; MyClass(int v) {val = v;} }; template<typename T> int MyClass<T>::bar; template class MyClass<Foo>; template class MyClass<Bar>; MyClass<Foo>* foo1 = new MyClass<Foo>(10); MyClass<Foo>* foo2 = new MyClass<Foo>(15); MyClass<Bar>* bar1 = new MyClass<Bar>(20); MyClass<Bar>* bar2 = new MyClass<Bar>(35); int f1 = foo1->val;//15 int f2 = foo2->val;//15 int b1 = bar1->val;//35 int b2 = bar2->val;//35
但在Java中,MyClass类的静态变量会由所有MyClass实例共享,无论类型参数相与否。
由于架构设计上的差异,Java泛型和C++模板还有如下很多不同点;
1. C++模板可以使用int等基本数据类型。Java则不行,必须转而使用Integer
2. Java中,可以将模板的类型参数限定为某种特定类型。例如,你可能会使用泛型实现CardDeck,并规定参数必须扩展自CardGame。
3. C++中,类型参数可以实例化,Java不可以实例化
4. Java中,类型参数(即MyClass<Foo>中的Foo)不能用于静态方法和变量,因为他们会被MyClass<Foo>和MyClass<Bar>共享。但在C++中,这些类是不同的,类型参数可以用于静态方法和静态变量。
5. 在Java中,不管类型参数是什么,MyClass的所有实例都是同一类型。类型参数会在运行时被抹去。而C++中,参数类型不同,实例类型也不同
Java的泛型和C++模板,虽然在很多方面看起来都一样,实则大不相同。
只是两个语言实现这个目的的手段不同而已,C++使用的是“代码生成”的方式,而Java使用的是“类型擦除”的方式。
“代码生成”:编译器在编译期间识别实际传入的参数类型,生成用于该类型的代码。
“类型擦除”:编译器在编译期间将实际类型擦除,将每个类型都视为Object类型。
例如,假设有一下java 代码:
[java] view plain copy print?Vector<String> vector = new Vector<String>();
vector.add(new String(“hello”));
String str = vector.get(0);
Vector<String> vector = new Vector<String>(); vector.add(new String("hello")); String str = vector.get(0);
编译时,上面的代码会被改写为:
[java] view plain copy print?Vector vector = new Vector();
vector.add(new String(“hello”));
String str = (String)vector.get(0);
Vector vector = new Vector(); vector.add(new String("hello")); String str = (String)vector.get(0);
有了Java泛型,我们可以做的事情也并没有真正改变多少;它只是让代码变得漂亮些。鉴于此,Java泛型有时也被成为”语法糖“。
这点跟C++的模板截然不同。
在C++中,模板本质上就是一套宏指令集,只是换了个名头,编译器会针对每种类型创建一份模板代码的副本。
有个证据可以证明这一点:MyClass<Foo>不会与MyClass<Bar>共享静态变量。然而,两个MyClass<Foo>实例则会共享静态变量。
[cpp] view plain copy print?/* * MyClass.cpp * * Created on: 2015?7?24? * Author: nanzhou */ template<class T> class MyClass { public: static int val; MyClass(int v) {val = v;} }; template<typename T> int MyClass<T>::bar; template class MyClass<Foo>; template class MyClass<Bar>; MyClass<Foo>* foo1 = new MyClass<Foo>(10); MyClass<Foo>* foo2 = new MyClass<Foo>(15); MyClass<Bar>* bar1 = new MyClass<Bar>(20); MyClass<Bar>* bar2 = new MyClass<Bar>(35); int f1 = foo1->val;//15 int f2 = foo2->val;//15 int b1 = bar1->val;//35 int b2 = bar2->val;//35
/* * MyClass.cpp * * Created on: 2015?7?24? * Author: nanzhou */ template<class T> class MyClass { public: static int val; MyClass(int v) {val = v;} }; template<typename T> int MyClass<T>::bar; template class MyClass<Foo>; template class MyClass<Bar>; MyClass<Foo>* foo1 = new MyClass<Foo>(10); MyClass<Foo>* foo2 = new MyClass<Foo>(15); MyClass<Bar>* bar1 = new MyClass<Bar>(20); MyClass<Bar>* bar2 = new MyClass<Bar>(35); int f1 = foo1->val;//15 int f2 = foo2->val;//15 int b1 = bar1->val;//35 int b2 = bar2->val;//35
但在Java中,MyClass类的静态变量会由所有MyClass实例共享,无论类型参数相与否。
由于架构设计上的差异,Java泛型和C++模板还有如下很多不同点;
1. C++模板可以使用int等基本数据类型。Java则不行,必须转而使用Integer
2. Java中,可以将模板的类型参数限定为某种特定类型。例如,你可能会使用泛型实现CardDeck,并规定参数必须扩展自CardGame。
3. C++中,类型参数可以实例化,Java不可以实例化
4. Java中,类型参数(即MyClass<Foo>中的Foo)不能用于静态方法和变量,因为他们会被MyClass<Foo>和MyClass<Bar>共享。但在C++中,这些类是不同的,类型参数可以用于静态方法和静态变量。
5. 在Java中,不管类型参数是什么,MyClass的所有实例都是同一类型。类型参数会在运行时被抹去。而C++中,参数类型不同,实例类型也不同
Java的泛型和C++模板,虽然在很多方面看起来都一样,实则大不相同。
相关文章推荐
- Java 中的泛型与 C++ 模板的比较
- C#和Java的泛型、C++模板、C#的constraints特性以及弱类型化和强类型化的问题(转)
- C++、C#、JAVA中模板与泛型
- JAVA的泛型和C++的模板的区别与联系
- Java 中的泛型与 C++ 模板的比较
- JAVA的泛型和C++的模板的区别与联系
- C++中模板和java中泛型的区别
- JAVA中的泛型和C++中的模板不一样
- Java 中的泛型与 C++ 模板的比较
- C++的模板(和java的泛型一样)
- C++和java中泛型的区别
- C#中的泛型与C++中的模板
- 一个泛型句柄类--C++模板和泛型编程--c++ primer
- Java JNI由浅入深(包括:Java和C++互传ArrayList泛型对象参数)
- C++ 模板和 C# 泛型之间的区别(C# 编程指南)
- hdu4762Cut the Cake(概率+大数操作(java)+C++高精度模板)
- C#中的静态构造函数 静态类 C# 泛型和 C++ 模板之间的主要差异
- C++ 模板和 C# 泛型之间的区别
- C++ Coding Standards:模板和泛型
- Java JNI由浅入深(包括:Java和C++互传ArrayList泛型对象参数)