Java和C++在细节上的差异(四)(三)

2014-11-24 02:04:05 · 作者: · 浏览: 2
中没有这样的限制,因此模板类的增多只会影响编译的效率和不会影响运行时的效率。
2) 运行时的类型查询只适用于原始类型,即if (a instanceof Pair) 等价于if (a instanceof Pair)。
3) 泛型类对象调用getClass()方法返回的Class对象都是擦除类型信息的原始Class类型,因此在做比较时,他们将为真,见如下代码:

1 publicclassTestMain {
2 publicstaticvoidmain(String[] args) {
3 MyClass i = newMyClass(5);
4 MyClass d = newMyClass(5.0);
5 //返回的均为MyClass.Class
6 if(d.getClass() == i.getClass())
7 System.out.println("Type info will be ignored here");
8 }
9 }
10 classMyClass {
11 publicMyClass(T t) {
12 this.t = t;
13 }
14 publicT getValue() { returnt;}
15 privateT t;
16 }
17 /* 输入结果:
18 Type info will be ignored here
19 */

4) 泛型类不能实现Throwable接口,换言之泛型类不能成为异常类,否则会导致编译错误。
5) 不能声明参数化类型的数组,如Pair[] table = new Pair[10]; 在擦除类型后将会变为Pair[] table = new Pair[10]; 因此可以执行该转换:Objec[] objarray = table; 由于数组可以记住元素的类型,如果此时试图插入错误的类型元素,将会导致异常ArrayStoreException的抛出。C++中没有该限制。
6) 不能实例化泛型类型的变量,如public Pair() { first = new T(); second = new T();},C++中不存在这样的限制,针对以上写法,类型T只要存在缺省的构造函数即可。如果确实需要实例化类型参数的对象,见如下代码:

1 publicstatic Pair makePair(Class c1) {
2 returnnewPair(c1.newInstance(),c1.newInstance());
3 }
4 publicstaticvoidmain(String[] args) {
5 //String.class的类型为Class
6 Pair p = Pair.makePair(String.class);
7 }

这里主要是利用Class类型本身也是泛型类型,可以利用Class的类型参数推演出Pair中T的类型。同样的道理带有类型参数的数组对象也不能直接创建,需要利用Array的反射机制来辅助完成,见如下代码:

1 publicstatic T[] minmax(T[] a) {
2 T[] mm = (T[])Array.newInstance(a.getClass().getComponentType(),a.length);
3 //do something here based on mm
4 returnmm;
5 }

7) 泛型类不能应用于静态上下文中,见如下代码:

1 publicclassSingleton {
2 publicstaticT getInstance() { //Compilation ERROR
3 returnsingleInstance;
4 }
5 privateT singleInstance; //Compilation ERROR
6 }

因为这样的写法在定义Singleton和Singleton之后,由于类型擦除,将会生成唯一一个Singleton原始共享对象,事实上这并不是我们所期望的结果,在C++中没有这样的限制,甚至有的时候还可以利用这样的机制针对不同类型的对象作声明计数器用,见如下代码:

1 template
2 classMyClassCounter {
3 public:
4 MyClassCounter(T t) {
5 _t = t;
6 _counter++;
7 }
8
9 operatorT() {
10 return_t;
11 }
12
13 T* operator->() {
14 return&_t;
15 }
16 intgetCount() const{ return_counter; }
17 private:
18 T _t;
19 staticint_counter;
20 }

8) 泛型类不能同时继承或实现只是拥有不同参数类型的同一泛型类,如public class MyClass implements Comparable, Comparable {}
7. 泛型类型的继承规则:
1) 如果public class Manager extends Employee {},那么Pair pe = new Pair()将会是非常的赋值操作,会导致编译错误。试想如下代码引发的运行时问题。在C++中这种赋值方式同样会导致编译错误,因为他们在类型实例化之后就被视为完全无关的两个类型。

1 publicvoidtest() {
2 Pair manager = newPair();
3 Pair employee = manager; //compilation error
4 employee.setFirst(otherEmployeeButNotManager); //employee的另外一个子类,但不是Manager。
5 }

2) 数组由于在运行时会记住元素的类型,因此数组可以完成这样的赋值,如Manager[] manager = {}; Employee[] employee = manager;如果赋值之后出现错误的元素赋值将会引发ArrayStoreException异常。
3) 泛型类型可以直接赋值给擦除类型后的原始类型,但是同样也会出现2)中数组赋值的问题,只是触发的异常改为ClassCastException,见如下代码:

1 publicvoidtest() {
2 Pair manager = newPair();
3