论坛首页 编程语言技术论坛

java和C#的泛型比较

浏览 24364 次
精华帖 (18) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-03-13  
OO
C#的泛型:

C#泛型类在编译时,先生成中间代码IL,通用类型T只是一个占位符。在实例化类时,根据用户指定的数据类型代替T并由即时编译器(JIT)生成本地代码,这个本地代码中已经使用了实际的数据类型,等同于用实际类型写的类,所以不同的封闭类的本地代码是不一样的。按照这个原理,我们可以这样认为:

泛型类的不同的封闭类是分别不同的数据类型。


java的泛型

对java虚拟机来说是没有泛型类的。java编译器在编译泛型类是会用泛型类的左边第一个限定类去替换。eg: ArrayList<T extend a & b>
编译后ArrayList的所以T会被a 去替换。但put数据是。编译器会检查put的数据是不是a类型的。但get数据时。他会返回a类型的数据.并添加类型转换代码。(这样效率就低了)
eg: ArrayList<News> arrayList=new ...; arrayList.get(0);
编译器会返回 a类型的数据。然后把 数据转换成News数据。
总之java没有泛型类。在编译后都是基本的类型。并加类类型转换。


这是我的看法。希望有人交流交流
   发表时间:2009-03-14  
膨胀法和擦除法。。。。擦除法基本就是伪泛型,不停的装箱拆箱。
0 请登录后投票
   发表时间:2009-03-19  
泛型也就那么回事吧。写代码方便而已。
0 请登录后投票
   发表时间:2009-03-23  
mooniscrazy 写道
泛型也就那么回事吧。写代码方便而已。



写代码方便? 你再开玩笑吧?有了泛型写代码还的多打好几个字<...>呢,如果你这样看泛型,那你就根本没学好泛型
0 请登录后投票
   发表时间:2009-03-23  
ray_linn 写道
mooniscrazy 写道
泛型也就那么回事吧。写代码方便而已。

写代码方便? 你再开玩笑吧?有了泛型写代码还的多打好几个字<...>呢,如果你这样看泛型,那你就根本没学好泛型

呵呵,说写代码方便也可以,典型的场景是声明了泛型容器之后,从容器取出元素的时候不必显式写类型转换。不过要注意的是Java泛型是擦除法,自己的代码里不写类型转换不代表没转换——编译器会插入相关的类型转换代码,来保证运行时的类型安全。
不过泛型确实不只是“写代码方便”那么简单就是了,呵呵。有没有人想过在.NET里用了泛型之后方法调用反而可能变慢?呵呵,要是一直有在用Mono的话就会知道我在说什么。
0 请登录后投票
   发表时间:2009-03-23   最后修改:2009-03-23
EnsureCapacity(int) 似乎对泛型的效率影响颇大,如果size设置过小的花,generic是有可能比none-generic慢,不知道是否还有其他情况?

大部分情况下, C#的泛型会比非泛型快不少,java的泛型会比非泛型慢一些。
0 请登录后投票
   发表时间:2009-03-24  
都是牛人啊,你们是不是.net和java都用啊。
0 请登录后投票
   发表时间:2009-03-24   最后修改:2009-03-24
ray_linn 写道
EnsureCapacity(int) 似乎对泛型的效率影响颇大,如果size设置过小的花,generic是有可能比none-generic慢,不知道是否还有其他情况?

大部分情况下, C#的泛型会比非泛型快不少,java的泛型会比非泛型慢一些。

Java的泛型与非泛型在不考虑reify type的时候其实在运行时没啥区别吧?至少编译出来的代码是一样的。参考一下这里最底下我的回帖

.NET的泛型比非泛型慢的状况貌似有好些。
我有个模糊的印象,如果泛型的实现不好的话,泛型方法查找(lookup)反而会比非泛型的慢;但刚才想找实例来支持我这个印象却一时没找到。明明记得我见过例子的……
至于我记得的:泛型类中的受泛型参数影响的方法需要分别实例化,在JIT之后的代码可能位于内存中不同的位置;如果程序中经常要处理同一泛型类型的同一方法的不同实例,则它们很可能得不到locality的好处。现代处理器里cache miss对性能的影响也可以很要命。
在Miguel的blog上有过一篇记录,关于Mono的泛型代码共享的,Generics Memory Usage。其中引用了另外一段:
引用
List<T> offers generally better performance than ArrayList as well as type safety. We recommend using List<T> over ArrayList always if T is a reference type. If T is a value type there is additional cost assocated with creating a specialized version of List<T> for that value type. When T would be a value type we recommend List<T> if the savings in boxing is greater than the cost of the additional code -- this tends to happen if you store about 500 elements across all your List<T> objects.

嘛,除了locality问题之外,泛型类/方法的实例化本身也对性能是个影响就是了。就纯速度角度看,泛型版本在免除装/拆箱和某些冗余的类型检查后并不总是比非泛型的快。不过就代码的可维护性而言,用泛型通常不是件坏事,呵呵。

kulinglei 写道
都是牛人啊,你们是不是.net和java都用啊。

不太清楚ray_linn大大如何,貌似是用微软系技术多些?我的话日常生活用Ruby最多,做作业得用Java,然后.NET也看看 ^ ^
0 请登录后投票
   发表时间:2009-03-24   最后修改:2009-03-24
关于性能,基本同意RednaxelaFX的看法。

Java既然是擦除法,这就意味着编译出来的JVM指令和非泛型是一样的。效率应该没有区别。

C# 不是很了解。但我知道一点, C#的泛型是在运行期,用Reflection动态查询具体泛型的。因为.Net的具体泛型对象里面包含有类型信息。
注:Java没有这种能力,因为具体对象里面并没有包含类型信息。Java的(属于Class)常量池中会存放一些泛型成员(属性或者方法)的泛型字符串信息,但那些都是静态信息,程序可以在运行期读取这些静态类型声明信息,但也就到此为止了。

-----------------------------------------

从使用角度来说,C#的泛型自然更加强大,因为可以真正实现动态Reflection泛型信息。但是,从设计思路来看,这种强大功能是否符合需要?是否应该提倡?

个人偏见,泛型的主要目的是编译期类型检查,而不是丰富动态类型信息。
从这点来看,Java的泛型设计,恰到好处。擦除法完全是在编译器中实现的,正符合编译期类型检查的目的。

C# 泛型的设计就过了一点,实现得更加彻底。
当然,从程序员的角度来说,会更喜欢 C# 泛型,因为 C# 泛型提供了更加强大的功能。虽然这功能也许是不需要的,或者说,不应该需要的。

0 请登录后投票
   发表时间:2009-03-24   最后修改:2009-03-24
RednaxelaFX 写道
Java的泛型与非泛型在不考虑reify type的时候其实在运行时没啥区别吧?至少编译出来的代码是一样的。参考一下这里最底下我的回帖


虽然代码类似,但在应用场景中,Java泛型强制了装箱和拆箱,在某些本不需要拆装箱的场景下,会有多余动作。


RednaxelaFX 写道

.NET的泛型比非泛型慢的状况貌似有好些。
我有个模糊的印象,如果泛型的实现不好的话,泛型方法查找(lookup)反而会比非泛型的慢;但刚才想找实例来支持我这个印象却一时没找到。明明记得我见过例子的……
至于我记得的:泛型类中的受泛型参数影响的方法需要分别实例化,在JIT之后的代码可能位于内存中不同的位置;如果程序中经常要处理同一泛型类型的同一方法的不同实例,则它们很可能得不到locality的好处。现代处理器里cache miss对性能的影响也可以很要命。


对于频繁拆装箱的情况下,泛型的性能优势才能体现出来。比如Cecil中,我将许多Collection改为Generic版本,根据我的测试结果,代码复杂度和执行效率都有显著改善,尤其是代码复杂度。

当然明确的是,Generic不是为性能而设计的,但是我们在选择Collection的时候,还是应该首选考虑generic
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics