K)流程控制:有差别的是switch,Java沿用了C++做法,分支可以重叠,但C#要求每个分支都必须有break.从防止出错上来说,C#比较好,但不可避免的会失去很多技巧性写法和灵活性。
1) I/O:这个东西其实比较没什么意义,不过java的流概念跟C#的流概念其实都差不多,继承体系都差不多,只是Java中是Input,Output,而C#中是Read和Write.其实各自支持类中的方法名大部分都相同.当然,C# 除了流支持外,还兼容原来的一些文件读写.
2)序列化:对象的序列化两者都有支持,做法都差不多,当然,C# 中除了二进制序列化外,还可以序列化成XML格式(Java中有不有还有待更进一步了解).序列化的用途其实也差不多(主要是RMI).
3)反射机制:两者的反射机制差不多,当然,在这个方面C#的要完善一些,还加入了元属性(Attribute)的概念(Java中有不有类似的东西,学到目前还没发现,Java中的注解在C#中应该是///表达的东西).C#的反射内在机制我比较了解,Java的就不是很了解。但这种东西在Delphi中很早就有类似实现,只是没有现在的C#这样完善。当然,delphi还是欠缺些,而Java和C#都足够用。
4)多线程:这个其实是与语言无关的东东,不过在Java和C#中基本的实现方法还是差不多,类名都一样,只是方法名一个是run,一个叫Execute.Java中可以用Runable接口来简化线程的创建,C# 中是用方法和委托(包括Lamda表达式)来完成同样的工作.C#中的线程池(严格讲这属于框架而不是语言),后台任务之类的可以看作是一些二次封装的东西,没有对比的价值.
5)代码注入:C#和Java都是基于中间语言(C#的IL,Java的字节码),因此在实现代码注入上都比较方便,因此Spring中的面向方面的实现方法在C#中也很容易实现(可以参考我前面的博文).
6)重载:双方都支持方法的重载,而且规则基本差不多.为了简化这种重载C#中可以用参数缺省和params关键字来减少方法的个数,比如public void DoF(params object[] pms),调用的时候可以是DoF(p1),也可以是DoF(p1,p2...)等,这个在Java中是使用"..."来定义的:public void DoF(Object...pms).Java不支持参数缺省,参数缺省有其方便性,但不是必需(Delphi中很早就支持)。
7)委托和事件:这是带有函数指针,回调方法等味道的东东,找了一下,在Java中没有类似的概念,如果需要实现类似的东西,需要用到设计模式,比如观察者,代理等。C#,Delphi都有这个东西,这其实还是个非常好用的东西。我觉得Java完全可以借鉴升级一下(我查了一下,Java确实没有类似的东西,当然,也可能是我孤陋寡闻),Java没有这个可能是源于对纯面向对象语言的追求和对指针滥用的某种不安。
补充:经过查阅资料,Java中也有回调函数的实现,但实际上,这不是真正意义上的回调函数,只是一种模拟类似功能的东西.因为其传入的其实不是方法,而是类.从这个角度来看,我前面说的关于Java没有委托和事件的原因,估计是对的.
8)逆变和协变:其实只要是面向对象编程,存在继承就有这两种情况(方法的参数和返回值)。但大家只要把握一个原则:老子能用的地方儿子也能用,反之则不然。
总结:如果你对数据结构,操作系统,算法,面向对象编程等比较了解,其实相互转换还是比较容易的。做为苦B的程序员,完全没有必要为语言的排名而纠结,学习语言要有凌驾于语言层面之上的意识。
1) 基本架构
两者的基本架构也差不多,Java:Java程序->Java字节码->JVM(JIT).DotNet:C#程序->CIL(通用中间语言)->CLR(JIT).开始的时候Java的字节码是解释执行的,但现在使用的是即时编译技术,C#作为后来者,从一开始就采用了这种技术.就软件的执行架构来说是基本相同的;
2)平台无关性:
Java和DotNet的设计的目标都是平台无关的,但由于微软的操作系统是其主要赢利来源,所以.Net的平台无关性还是大打折扣.不过后面的Java也很难讲,毕竟被oracle收购后,有些东西会改变.
3)开发语言统一:
在这方面Java的设计没有包含这一目标,而dotNet从开始就致力于开发语言的统一,但这个不是java与C#的作为语言的区别,而是两个体系的不同.Dotnet的这一优势对于程序员来说还是比较有吸引力,至少减少了学习成本.但从另一个方面来说,Java和C#相互转换的学习成本都不是很高.
4)基本数据类型:Java的预定义基本类型要少很多,C#的多很多,但这个不妨碍正常使用.当然,由于C#是基于.net框架,其类型也是通用数据类型.由于两者都是为跨平台而设计的,因此其数据类型的长度并不是实际占用内存的大小.实际占用内存大小取决于虚拟机(JVM,CLR)和具体的机器类型(CPU字长).比如byte是8位,假设机器是32位的,你硬是将byte实现为8位,效率肯定会低些(每次取32位,然后通过计算分字节来取).
1、多线程
多线程模型基本相同,都有线程和线程池概念,调用方法一基本相同。线程基类都叫Thread.但由于Java不支持函数引用(delegate),因此线程代码只能以实现了Runnable或者继承Thread的对象的run方法来完成,相对C#来说不够简洁。Java中的线程组和C#中线程池概念类似,但区别还是非常大,Java中的线程组是可以自己创建自己管理的,比较灵活,可控性比较强,而C#中的线程池是由DotNet框架维护,与操作系统比较紧密,是为了减少线程创建开销,而实现的一种线程共享机制,因此性能上比较好。当然,用户的可控性就差一些。 另外Java中的线程组最终可以形成一个线程组树,而C#中的线程池则没有这种机制。
在多线程同步方便,Java提供的机制比较简单,而C#提供的控制更丰富一些。
2、类
主要不同如下:
1)默认的访问级别不同,不特别指明访问级别的情况下,Java默认是公共的(public),C#是私有的;
2)Java的继承是是用extends,实现接口是implements,而C#都是冒号(:)
3)C#提供的internel,Java没有对应的控制方式。
4) Java 不能定义静态类;
当然这都是细节上的差异,但对于嵌套类,双方的处理差别还是很大的,C# 对嵌套类的处理比较简单,嵌套类只是一种定义在类中的类类型,除了访问需要使用路径外(类A中嵌套类别B,则类B的访问是A.B),其它与正常类没什么不同。但Java的处理要复杂些,如果类B是类A中的嵌套类,Java认为类B是属于类A的实例对象的(如果在第3方使用B时,不能用A.B theB = new A.B()完成实例化,而必须类似A theA = new A();A.B theB = theA.new B() 来完成实例化。而且对B有如下限制:
1)在如果不指明B是静态类,则在B中不能定义静态方法,但这个静态指示定义的静态类跟C#有很大的差别,这里的静态指示(static)只是告诉编译器类B有静态方法。虽然类B有static修饰,类B还是可以实例化的,还是是动态类。
2)对于顶层类来说,可以定义静态方法,而嵌套类如果需要定义类方法,则必须使用static修饰符号来修饰类声明。
因此严格来说Java没有C# 那样严格意义上的静态类,Java的静态方法应该叫类方法比较好。
总体来说,Java和C#的机制和语法其实都很相似,但细节上还是有很多的差异。具体的差异可以在实践中再去学习,对于比较生僻的地方的差异也没比要都弄清楚,毕竟学习语言是用来编程解决问题的,而不是用来咬文嚼字的。
测试: