`
kulinglei
  • 浏览: 99439 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

java和C#的泛型比较

阅读更多
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没有泛型类。在编译后都是基本的类型。并加类类型转换。


这是我的看法。希望有人交流交流
分享到:
评论
13 楼 ray_linn 2009-03-24  
RednaxelaFX 写道

ray_linn大大给出的他对Cecil的改进就是一个例子(话说我也有自己修改的Cecil版本,这玩儿就不能抛弃向后兼容性来点速度么 OTL)



我对Cecil的改进主要是两个方面,一个是通过泛型取消冗余代码,降低代码的维护难度,同时也增加一些性能,毕竟分析一个Assembly里的元素是比较庞大的,减少拆箱装箱是有意义的。

另一个方面是尝试引入PLINQ,用多线程帮助代码分析。。。基本是成功的。

我能想到的就基本只有这两个手段了。。。
12 楼 ray_linn 2009-03-24  
RednaxelaFX 写道
可以举个简单的例子么?一时想不出来实例,觉得不太形象。
对于原始类型,Java编译器会插入装箱/拆箱;对于引用类型,如果泛型参数类型出现在返回类型的位置上,那么编译器会在调用方插入强制类型转换,如果出现在参数位置上则会在被调用方插入强制类型转换。不知道大大说的是哪些状况会出现多余动作?



比如一个MyCollection<T>, 它有一个Add(MyCollection<T> sub)的方法,这个方法众所周知就是foreach sub,然后调用Get和Add的方法,每一次从sub里get一个item就要装箱一次,往parent里add一个item就要拆箱一次,个人认为效率应该比非泛型的collection差。


public void add(MyCollection<T> sub){

  for(int i=0;i<sub.size();i++){
     T item=sub.get(i); //装箱
      this.add(item);//拆箱

  }
}

public void add(MyCollection sub){
     for(int i=0;i<sub.size();i++){
     Object item=sub.get(i); //不装箱
      this.add(item);//不拆箱

  }
}


不知道是否有误?
}
11 楼 whaosoft 2009-03-24  
java的泛型和c++还不一样
他只是类型检查~
10 楼 RednaxelaFX 2009-03-24  
buaawhl 写道
个人偏见,泛型的主要目的是编译期类型检查,而不是丰富动态类型信息。

嘛……“真”泛型的话,性能普遍来说还是有提升的。类型检查在虚方法+迟绑定这样的场景里,许多时候得压到运行时做,而真泛型能让编译器在编译时多提供些保证,因而可以直接消除部分的运行时开销(以另一些小一些的开销为代价);擦除式泛型无法提供这样的静态保证,所以仍然需要插入类型检查的代码,这样实际上没有在编译时带来特别大的好处(你仍然需要担心别人把你的ArrayList<E>当成非泛型的ArrayList来用),只是在“正常”的应用场景里程序员可以少打几个类型转换。
ray_linn大大给出的他对Cecil的改进就是一个例子(话说我也有自己修改的Cecil版本,这玩儿就不能抛弃向后兼容性来点速度么 OTL)
我提到泛型代码可能比非泛型慢主要是想引起注意:许多人认为真泛型天生就应该比非泛型代码快;事实上不总是这样,所以我举了些可能会慢的状况。

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

可以举个简单的例子么?一时想不出来实例,觉得不太形象。
对于原始类型,Java编译器会插入装箱/拆箱;对于引用类型,如果泛型参数类型出现在返回类型的位置上,那么编译器会在调用方插入强制类型转换,如果出现在参数位置上则会在被调用方插入强制类型转换。不知道大大说的是哪些状况会出现多余动作?

ray_linn 写道
但是我们在选择Collection的时候,还是应该首选考虑generic

嗯,这点完全同意。诶,像是有时候见到IEnumerable反而头疼,还得加个.Cast<T>()的调用才能接上LINQ T T
9 楼 ray_linn 2009-03-24  
RednaxelaFX 写道
Java的泛型与非泛型在不考虑reify type的时候其实在运行时没啥区别吧?至少编译出来的代码是一样的。参考一下这里最底下我的回帖


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


RednaxelaFX 写道

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


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

当然明确的是,Generic不是为性能而设计的,但是我们在选择Collection的时候,还是应该首选考虑generic
8 楼 buaawhl 2009-03-24  
关于性能,基本同意RednaxelaFX的看法。

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

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

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

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

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

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

7 楼 RednaxelaFX 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也看看 ^ ^
6 楼 kulinglei 2009-03-24  
都是牛人啊,你们是不是.net和java都用啊。
5 楼 ray_linn 2009-03-23  
EnsureCapacity(int) 似乎对泛型的效率影响颇大,如果size设置过小的花,generic是有可能比none-generic慢,不知道是否还有其他情况?

大部分情况下, C#的泛型会比非泛型快不少,java的泛型会比非泛型慢一些。
4 楼 RednaxelaFX 2009-03-23  
ray_linn 写道
mooniscrazy 写道
泛型也就那么回事吧。写代码方便而已。

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

呵呵,说写代码方便也可以,典型的场景是声明了泛型容器之后,从容器取出元素的时候不必显式写类型转换。不过要注意的是Java泛型是擦除法,自己的代码里不写类型转换不代表没转换——编译器会插入相关的类型转换代码,来保证运行时的类型安全。
不过泛型确实不只是“写代码方便”那么简单就是了,呵呵。有没有人想过在.NET里用了泛型之后方法调用反而可能变慢?呵呵,要是一直有在用Mono的话就会知道我在说什么。
3 楼 ray_linn 2009-03-23  
mooniscrazy 写道
泛型也就那么回事吧。写代码方便而已。



写代码方便? 你再开玩笑吧?有了泛型写代码还的多打好几个字<...>呢,如果你这样看泛型,那你就根本没学好泛型
2 楼 mooniscrazy 2009-03-19  
泛型也就那么回事吧。写代码方便而已。
1 楼 ray_linn 2009-03-14  
膨胀法和擦除法。。。。擦除法基本就是伪泛型,不停的装箱拆箱。

相关推荐

    关于C#、java泛型的看法

    谈谈关于Microsoft Visual Studio 2008中C#和java泛型的区别

    泛型反射例子

    JAVA中 关于泛型 以及反射的例子 欢迎下载 一起研究

    C# To JAVA Converter v17.10.6

    使用Java泛型转换C#ref参数 当代码中定义事件委托时转换C#事件,或者是System.Action或System.Func代理之一 将所有类型的数组从C#转换成Java 对于继承和接口的所有方面,从C#到Java的无瑕疵转换 允许自定义替换...

    你真的懂Java泛型吗?

    在JDK 1.5开始引入了泛型,但Java实现泛型的方式与C++或C#差异很大。在平常写代码用到泛型时,仿佛一切都来得如此理所当然。但其实Java泛型还是有挺多tricky的东西的,编译器在背后为我们做了很多事。下面我们来看看...

    c# 反射获取传入对象的属性拼接sql语句实现增、删、改、查

    利用反射动态拼接sql。 daohelper属于DAL层,objectdata类属于BLL层,BLL层引用DAL层。映射数据的表继承objectdata类。例如,数据表book,根据字段与属性一一对应的方式创建book类,插入数据库时,直接book.save()

    快速了解泛型(C#,JAVA,C++)

    泛型其实就是能够向你的类型中加入类型参数的一种能力,也称作参数化的类型或参数多态性

    开发专家·编程大讲坛:C#核心开发技术从入门到精通.tag.pdf

    依次讲解了C#开发基础、搭建C#开发环境、变量与常量、复杂的变量类型和.NET框架类、表达式和运算符、流程控制...和事件、C#泛型、C#文件操作和流文件操作、XML文件操作处理、C#的Windows编程基础、菜单、工具栏和对话框...

    Silverlight与Java通信远程调用封装

    可以转换日常使用中的任意复杂类型通信,成功解决C# DateTime和Java Date传递问题,解决java容器泛型与C#容器泛型转换问题,解决复杂对象问题(对象属性是另外对象,容器中套容器)等。 欢迎大家使用,有问题,可以...

    c#分页方案

    提供三种.net分页方案,总结既详细又简单实用

    Java泛型类型通配符和C#对比分析

    下面小编就为大家带来一篇Java泛型类型通配符和C#对比分析。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    泛型约束,.NET 中越来越多的使用到泛型

    泛型,无论在Java中还是在C#中,应用都很广泛,可以解决很多关于类型的问题

    自定义的Troop&lt;T&gt;泛型类( c++, java和c#)的实现代码

    主要介绍了自定义的Troop泛型类( c++, java和c#)的实现代码的相关资料,需要的朋友可以参考下

    java笔试题算法-C5:用于C#/.NET的C5泛型集合库

    编程语言和其他支持泛型的语言的一组泛型集合类(或容器类),由 Microsoft .NET 4.6.1+、.NET Core 2.0+ 实现,和单声道。 C5 库提供了广泛的经典数据结构、丰富的功能、最佳的渐近时间复杂度、记录的性能和经过...

    Generic Programming for Scientific Computing in C++, Java, and C#

    JavaTM and C# programming languages. In this paper, we evaluate these extensions with respect to the realm of scientific computing and compare them with C++ templates. At the heart of our comparison ...

    Apla→Java程序生成系统中泛型机制实现方法研究.pdf

    在对泛型程设本质特征深入研究的基础上提出了新型泛型语言机制构想,并在Apla→java生成系统...该方法比现有的java、C++、C#等语言中泛型机制的实现方法简单,并通过经典算法实例演示实现效果,大量用例的成功测试表明...

    关于C#编程语言的一些常见基础面试题.pdf

    2. C#与其他编程语言(如Java、C++等)有哪些不同之处?请说明C#相对于其他语言的优势。 3. C#中的命名空间(Namespace)是什么?请说明在C#中命名空间的作用和用法。 4. C#语言中的面向对象编程(Object-Oriented ...

    C#中数组Array,ArrayList,泛型List详细对比

    关于数组Array,ArrayList,泛型List,简单的说数组就是值对象,它存储数据元素类型的值的一系列位置.Arraylist和list可以提供添加,删除,等操作的数据. 具体如何进行选择使用呢,我们来详细探讨下

    C#实现利用泛型将DataSet转为Model的方法

    因为网站需要用C#开发,习惯了java的泛型,所以看了一下C#下,也可以这样做,随便写了一个。 public static List&lt;T&gt; PutAllVal(T entity, DataSet ds) where T : new() { List&lt;T&gt; lists = new List(); if (ds....

    c# 5.0 解析

    C#3 0加入了一堆语法糖 lambda linq的加入 让C#变得更加优雅和灵活; C#4 0增加了动态语言的特性 另外加入的TPL 并行开发库 PLinq等降低现存并发模型的复杂性也是相当的给力 C#5 0 还会有什么奇思妙想 "&gt;C# 5 0 not...

    java数据库增删改查操作实例(hibernate原理)支持泛型集合

    写了一个通用java访问数据库操作的DAO类,非常简单,非常强大,非常方便,非常好用。绝对原版,绝对原创。把hibernate彻底扔掉。(根据C#改编的,原本我是搞C#开发的)支持泛型集合,让程序运行效率更高。

Global site tag (gtag.js) - Google Analytics