Reifiable generics与Type erasure generics各有怎样的优点与缺点?

关注者
153
被浏览
5641
题主的问题是关于“parametric polymorphism”的不同实现方式的比较。

这些话题水都挺深的。关键是“reified generics”与“generics via erasure”这俩其实都是大的思路,可以对应到许多种不同的实现,每个小细节的差异都可能会带来不同的优缺点所以写起来很麻烦⋯

如果题主把问题收窄为:C#风格的“reified generics”与Java 5风格的“generics via erasure”个优缺点的对比的话那就比较容易精确回答——当然描述起来还是要写很多字。

为了偷懒省得自己码字,我要诚意送上若干传送门:
  • State of the Specialization <- 这篇文档是Brian Goetz(目前Java语言设计的架构师)写的调研报告,以及探索未来Java实现reified generics所制作的原型的实现方式。这里说的原型是第一版原型。
  • JVMLS 2015 - Adventures on the Road to Valhalla (打不开请自备工具⋯)<- 这是几天前刚开完的JVM Language Summit 2015上Brian Goetz的演讲,关于Java的reified generics的原型实现的现状和展望。这里说的原型是第三版原型,跟第一版相比已经颇有不同。
  • OpenJDK: Valhalla <- 这是探索未来Java引入用户自定义值类型(custom value type)与reified generics的OpenJDK项目。
  • JEP 218: Generics over Primitive Types <- 这是关于允许Java泛型拓展到支持primitive type的提案草案。
上面的传送门之中,第一个(State of the Specialization)的前半部分我觉得可以完美回答题主的疑问。它比较了三种泛型实现方式的优缺点:
  • C++:模板方式实现,在编译时完全展开并且支持偏特化,类型精度高,代码共享差;
  • Java 5:擦除方式实现,仅用于编译时类型检查,在运行时擦除,向后兼容性好,代码共享好,类型精度非常差;
  • C# 2.0:混合方式实现,在运行时展开特化,类型精度高,代码共享还行。
详情请跳进传送门阅读文档。我觉得Brian这篇调研写得非常好,我没啥可补充的。

再放个自己的传送门:C#泛型(MSIL)的内部是怎么实现的? - RednaxelaFX 的回答

=================================================

P.S. 很多人可能都只在乎erasure的纱布之处,但没关注过它带来的好处。

其实在有些场景这种做法还确实是有用处的。
举个例子:它允许了同一系列的泛型类型可以自动有共同基类,例如ArrayList<String>和ArrayList<Object>就可以有共同基类ArrayList<?>(擦除版)。假如说我们要从一个不太关心类型的语言调用Java的库方法,例如从Rhino / Nashorn所实现的JavaScript调用Java方法,就不用费力去指定那个泛型参数。
相比之下,在CLR上实现的IronPython和IronRuby在与C#代码交互时就经常被泛型参数绊到,不得不给语言发明扩展语法来指定泛型参数。例子请参考IronPython的文档:IronPython .NET Integration