锁定老帖子 主题:java和C#的泛型比较
精华帖 (18) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-03-13
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没有泛型类。在编译后都是基本的类型。并加类类型转换。 这是我的看法。希望有人交流交流 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-03-14
膨胀法和擦除法。。。。擦除法基本就是伪泛型,不停的装箱拆箱。
|
|
返回顶楼 | |
发表时间:2009-03-19
泛型也就那么回事吧。写代码方便而已。
|
|
返回顶楼 | |
发表时间:2009-03-23
mooniscrazy 写道 泛型也就那么回事吧。写代码方便而已。
写代码方便? 你再开玩笑吧?有了泛型写代码还的多打好几个字<...>呢,如果你这样看泛型,那你就根本没学好泛型 |
|
返回顶楼 | |
发表时间:2009-03-23
ray_linn 写道 mooniscrazy 写道 泛型也就那么回事吧。写代码方便而已。
写代码方便? 你再开玩笑吧?有了泛型写代码还的多打好几个字<...>呢,如果你这样看泛型,那你就根本没学好泛型 呵呵,说写代码方便也可以,典型的场景是声明了泛型容器之后,从容器取出元素的时候不必显式写类型转换。不过要注意的是Java泛型是擦除法,自己的代码里不写类型转换不代表没转换——编译器会插入相关的类型转换代码,来保证运行时的类型安全。 不过泛型确实不只是“写代码方便”那么简单就是了,呵呵。有没有人想过在.NET里用了泛型之后方法调用反而可能变慢?呵呵,要是一直有在用Mono的话就会知道我在说什么。 |
|
返回顶楼 | |
发表时间:2009-03-23
最后修改:2009-03-23
EnsureCapacity(int) 似乎对泛型的效率影响颇大,如果size设置过小的花,generic是有可能比none-generic慢,不知道是否还有其他情况?
大部分情况下, C#的泛型会比非泛型快不少,java的泛型会比非泛型慢一些。 |
|
返回顶楼 | |
发表时间:2009-03-24
都是牛人啊,你们是不是.net和java都用啊。
|
|
返回顶楼 | |
发表时间: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也看看 ^ ^ |
|
返回顶楼 | |
发表时间:2009-03-24
最后修改:2009-03-24
关于性能,基本同意RednaxelaFX的看法。
Java既然是擦除法,这就意味着编译出来的JVM指令和非泛型是一样的。效率应该没有区别。 C# 不是很了解。但我知道一点, C#的泛型是在运行期,用Reflection动态查询具体泛型的。因为.Net的具体泛型对象里面包含有类型信息。 注:Java没有这种能力,因为具体对象里面并没有包含类型信息。Java的(属于Class)常量池中会存放一些泛型成员(属性或者方法)的泛型字符串信息,但那些都是静态信息,程序可以在运行期读取这些静态类型声明信息,但也就到此为止了。 ----------------------------------------- 从使用角度来说,C#的泛型自然更加强大,因为可以真正实现动态Reflection泛型信息。但是,从设计思路来看,这种强大功能是否符合需要?是否应该提倡? 个人偏见,泛型的主要目的是编译期类型检查,而不是丰富动态类型信息。 从这点来看,Java的泛型设计,恰到好处。擦除法完全是在编译器中实现的,正符合编译期类型检查的目的。 C# 泛型的设计就过了一点,实现得更加彻底。 当然,从程序员的角度来说,会更喜欢 C# 泛型,因为 C# 泛型提供了更加强大的功能。虽然这功能也许是不需要的,或者说,不应该需要的。 |
|
返回顶楼 | |
发表时间:2009-03-24
最后修改:2009-03-24
RednaxelaFX 写道 Java的泛型与非泛型在不考虑reify type的时候其实在运行时没啥区别吧?至少编译出来的代码是一样的。参考一下这里最底下我的回帖?
虽然代码类似,但在应用场景中,Java泛型强制了装箱和拆箱,在某些本不需要拆装箱的场景下,会有多余动作。 RednaxelaFX 写道 .NET的泛型比非泛型慢的状况貌似有好些。 我有个模糊的印象,如果泛型的实现不好的话,泛型方法查找(lookup)反而会比非泛型的慢;但刚才想找实例来支持我这个印象却一时没找到。明明记得我见过例子的…… 至于我记得的:泛型类中的受泛型参数影响的方法需要分别实例化,在JIT之后的代码可能位于内存中不同的位置;如果程序中经常要处理同一泛型类型的同一方法的不同实例,则它们很可能得不到locality的好处。现代处理器里cache miss对性能的影响也可以很要命。 对于频繁拆装箱的情况下,泛型的性能优势才能体现出来。比如Cecil中,我将许多Collection改为Generic版本,根据我的测试结果,代码复杂度和执行效率都有显著改善,尤其是代码复杂度。 当然明确的是,Generic不是为性能而设计的,但是我们在选择Collection的时候,还是应该首选考虑generic |
|
返回顶楼 | |