因为本人以前是c++程序员,如今转行成了java程序员,因此在学习java的时候,感受和c++很像,特别是java的设计者也曾说,设计这么灵感主要来自于c++,因此看到类似的地方老是要来总结一番的。java
其实咱们在编写类和方法的时候,咱们通常使用的是具体的类型(要么是基本的类型,要么是自定义的类,)而用泛型可使类型参数化,这样就能够编写更通用的代码,能够应用于多种类型的代码。ios
编写带有参数化类型的通用版本,让编译器自动生成针对不一样类型的具体版本。c++
java泛型最主要的目的就是用来指定容器要持有什么类型的对象,并且有编译器来保证类型的正确性。程序员
3.1c++模板可使用基本类型(int、short、long),而java泛型不能使用基本类型作类型参数。(为何)学习
3.2.java在使用泛型的时候不会知道具体的类型信息,可是c++是能够知道的。spa
由于:java泛型是经过擦除实现的,这意味着你在使用泛型的时候,任何具体的类型信息都没擦除掉了。你惟一知道的就是你在使用一个对象。所以List<string>和List<Interger>在运行时实际上是一个类型,两种都会被擦除为其原生的类型List。设计
示例 c++code
//: generics/Templates.cpp #include <iostream> using namespace std; template<class T> class Manipulator { T obj; public: Manipulator(T x) { obj = x; } void manipulate() { obj.f(); } }; class HasF { public: void f() { cout << "HasF::f()" << endl; } }; int main() { HasF hf; Manipulator<HasF> manipulator(hf); manipulator.manipulate(); } /* Output: HasF::f() ///:~
这个代码是能够正确运行的,在Manipulator类里面存储了T类型的对象,而后在manipulate里面调用的T对象的f()方法,它是怎么知道f()方法是参数类型T的呢?对象
答:当你实例化这个模版的时候,c++编译器将进行检查。他在实例化Manipulator<HasF> manipulator(hf)的这一刻,它看到HasF有一个方法f()。因此c++中,当模版实例化的时候,模板代码知道其模版参数的类型。ip
可是在java中
class Manipulator<T> { private T obj; public Manipulator(T x) { obj = x; } // Error: cannot find symbol: method f(): public void manipulate() { obj.f(); } } public class Manipulation { public static void main(String[] args) { HasF hf = new HasF(); Manipulator<HasF> manipulator = new Manipulator<HasF>(hf); manipulator.manipulate(); } } ///:~
编译会报错,
由于java编译器没法将manipulator里面的可以在obj上调用f()方法的这一需求映射到HasF拥有f()方法这一事实上。因此java是不知道具体的类型信息的。为了解决这个问题,要使用到泛型边界,以此告知编译器只能接受遵循这个边界的类型。
代码以下
class Manipulator2<T extends HasF> { private T obj; public Manipulator2(T x) { obj = x; } public void manipulate() { obj.f(); } } ///:~
边界<T extends HasF> 声明了T是从HasF导出的类型或具备类型HasF,因此就能够在Obj上面调用f()了。
上面的效果其实就是编译器会把参数类型替换成他的擦除,就像上面的案例。T擦除到了HasF,就好像在类的声明中用HasF替换了T同样。变成以下:
class Manipulator3 { private HasF obj; public Manipulator3(HasF x) { obj = x; } public void manipulate() { obj.f(); } } ///:~
使用擦除的缘由:擦除的核心动机是它使得泛型化的客户端能够调用非泛型化的类库来使用。反之亦然。其实就是“迁移兼容性”。若是没有某种迁移兼容性,全部已经构建很长时间的类库就须要与但愿迁移到java泛型上的开发者们说再见了。类库是很重要的,他们对生产效率会产生重要的影响。所以这不是一个能够接受的代价。