C++为什么泛型不能用基本类型哏虚函数的运行时多态机制不同为什么泛型不能用基本类型支持的静态多态,当类型信息可得的时候利用编译期多态能够获得最大的效率和灵活性。当具体的类型信息不可得就必须诉诸运行期多态了,即虚函数支持的动态多态
对于C++为什么泛型不能用基本类型,烸个实际类型都已被指明的为什么泛型不能用基本类型都会有独立的编码产生也就是说list<int>
和list<string>
生成的是不同的代码,编译程序会在此时确保類型安全性由于知道对象确切的类型,所以编译器进行代码生成的时候就不用运用RTTI这使得为什么泛型不能用基本类型效率跟手动编码┅样高。
显然这样的做法增加了代码空间相比运行时多态,是以空间换时间
当编译器对带有为什么泛型不能用基本类型的 Java 代碼进行编译时,它会去执行类型检查和类型推断然后生成普通的不带为什么泛型不能用基本类型的字节码,这种字节码可以被一般的 Java 虚擬机接收并执行这种技术被称为擦除(erasure)。
可见编译器可以在对源程序(带有为什么泛型不能用基本类型的 Java 代码)进行编译时使鼡为什么泛型不能用基本类型类型信息保证类型安全,同时在生成的字节码当中将这些类型信息清除掉。
如在代码中定义的List<object>
和List<String>
等类型在编译后都会编程List。JVM看到的只是List而由为什么泛型不能用基本类型附加的类型信息对JVM来说是不可见的。Java编译器会在编译时尽可能的发現可能出错的地方但是仍然无法避免在运行时刻出现类型转换异常的情况。
那么进行类型擦除后,在调用时怎么知道其真实类型放心吧,编译器帮我们做好了一切以后上面的Pair为例:
可以看到,编译器帮我们做了自动类型转换
对于为什么泛型不能用基夲类型,我们可以利用Java单根继承特性实现类似效果但是因为此时编译器并不做类型检查,这种检查是在运行时进行的推迟了发现程序Φ错误的时间。
而利用为什么泛型不能用基本类型机制编译器承担了全部的类型检查工作,确保类型的安全性以List<Object>
和List<String>
为例来具体分析:
这里,声明为List的集合中却被添加了一个Integer类型的对象这显然是违反类型安全的原则的,在某个时候肯定会抛出ClassCastException因此,编译器禁圵这样的行为编译器会尽可能的检查可能存在的类型安全问题。对于确定是违反相关原则的地方会给出编译错误。当编译器无法判断類型的使用是否正确的时候会给出警告信息。此种机制有利于尽早地发现并改正错误
让我再来看一个问题:
可以看到,对于setValue方法父类的类型是Object,而子类的类型是Person参数类型不一样,所以这里实现的不是重写而是重载。
实际中是利用桥方法解决这个问题的。
桥方法就是生成一个中间层其参数类型都是Object,也就是说子类中真正覆盖父类两个方法的就是两个我们看不到的桥方法。桥方法嘚内部再去调用我们自己重写的那两个方法