java泛型的特殊之处

本文通过3个小例子,探索一下Java泛型和C++泛型的区别,说明Java泛型的一些特殊之处。

我们不探究语言背后的晦涩原理,而是从实际使用角度去理解它们。

代码地址:https://github.com/owenliang/java-generic-demo2

例子1

上述new T()的操作将无法编译通过,因为从java泛型实现原理来说,运行时T是什么类型已经不明确了,所以构造一个T类型对象就无从谈起。

而在C++模板则会在编译时直接生成模板类代码,其类型信息是明确的,不存在JVM这样运行时不知道T类型的情况:

上述代码完全正确,C++编译器为int类型的T生成了一份func1函数,因此如何new T()也是明确的,比java泛型要强大的多。

例子2

调用一下:

虽然T类型在JVM运行时丢失了类型信息,但是如果我们只是把T类型的对象挪来挪去,不访问对象内部的方法属性,那么编译运行是完全没问题的。

例子3

调用一下(把例子2的List<Integer> l传入):

函数func3对T类型进行了约束,要求它继承自List<>,并且List中的元素要继承自Number,说白了就是T必须是一个存放数字的列表。

相比于一个没有任何约束的T类型,这些约束其实给了JAVA编译器很多类型信息,因此我们可以直接调用size()方法,因为T一定继承自List;同时,我们从List<? extends Number>取出来的元素也一定继承自Number,所以可以调用Number类的doubleValue方法获取浮点数表示。

总结,java泛型因为其实现原理问题有一些奇奇怪怪的表现,相比于C++变态的模板编程来说其实算很简单的东西了。

我不建议为了使用泛型技术而去深钻java泛型背后的实现原理,从实用角度出发多尝试遇到问题再解决就好,这样生活会比较愉快。

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~