读《C# 和 Java 的比较》有感文章分类:Web前端 关键字: c# java网上的一篇《C# 和 Java 的比较》(或者叫《Java 和 C# 的比较》)写的挺不错的,今天忽然搜索到。 自己刚刚接触C#,也不由自主地随时都拿来和Java做对比,所以就心血来潮在原作者的每一条之后斗胆都写了些文字。就当是给自己再加深一遍印象吧。
【非常抱歉,由于网上此文章已经被转载多次,所以真的找不到原出处了,所以没法贴出作者原贴的连接】
开始吧...
2007年11月1日
评论:我很喜欢C#的internal,在Java如果一个为API中某些类提供服务的类,为了不对外暴露,只能用包级私有,并和被服务的类放在一个包中,如果有多个包中的类都要被服务,就没法办了。而C#的internal就很好的仅限当前“集合”(可能有多个namespace)中的类访问。 但是,我又不喜欢C#的“集合”的感念。反射的时候还必须给出DLL或EXE的文件名(如果不在当前DLL或EXE中),而Java是不需要的,只有在WEB-INF/classess和lib 下的都可以。特别是当API要反射它的调用者时,作为类库的DLL怎么知道哪个EXE在调用自己?
2。C#中有static constructor的概念,这跟java中的静态初始模块一样。
批注:原来是这样写,我找了半天也没搜到C#中的静态代码段如何个写法,如今得来全不费工夫。
批注:MS的人性化关怀呀。
批注:这个机制可能在特定场合下很有用。比如:抽签,这样你就不能耍赖了。
6.java在继承、多态方面,比C#强多了。Java默认的多态,C#要求加上virtual(被继承的方法)和override(继承的方法),而且C#要求不能改变原来的访问修饰符,不像java那样,可以指定更加宽松的访问方式。如果有人利用C#来写程序,必须经常带上virtual和override,还必须照抄原来的访问控制符,不会很郁闷吗?难道有人用C#的面向对象特性时,会舍弃多态的特性?这会引起多大的混乱啊。
批注:C#号称和Java有90%的相似性,但它必将是从C++发展而来的,在虚函数的概念上还是延续着C++的方式。习惯了Java之后,真的是感觉别扭。Java多好:默认情况下都是虚函数,允许被子类重写,但是对于有意不想让子类重写的方法用final关键字来修饰。
7. C#中new还可以用来指定子类的某个方法要隐藏父类的具有相同签名的方法。这是不是多余的?你不用也可以,不过csc.exe会警告你,如“lan.Other.Main(string[])”隐藏了继承的成员“lan.HelloWorld.Main(string[])”。如果是有意隐藏,请使用关键字 new。
批注:其实这个还是和6有关,总之对于Javaer来说就是两个字“别扭”。那些非虚函数干脆就不允许改写就得了,像Java的final那样。干嘛“既要做婊子又要立牌坊”呀,当警告超过一定数量时,估计就掩埋了,不容易被注意到。而真等到了使用的时候,哪一个是多态?哪一个是“另起炉灶”?使用者不晕菜才怪呢!
8.C#中,防止一个类被继承,要用关键字sealed。而定义一个常量时,要用const。
批注:这倒没什么,关键字都一样了,显得人家MS多没水平吗。我们只是需要再多记住一些东西就是了,多无奈呀。
批注:都是操作符重载惹的祸。Equals就是Equals;ReferenceEquals就是ReferenceEquals。但 == 可要注意了,有的时候是 Equals 有的时候是 ReferenceEquals。== 被重载了,我反而更不敢用了,还是稍微费点事写 Equals 和 ReferenceEquals 吧,即不会犯错误,有意义清晰。
10.C#中没有原始类型的包装类,但是也提供自动装拆箱的功能,和java有的一样。区别是,C#的装箱是自动的,拆箱就要强制转换了。
批注:包装类还是有的吧?如:int -> Int32;string -> String;甚至 object -> Object。是我的理解有误吗?至少从VS中关键字高亮的颜色就能区分开。
批注:这一点我没什么研究,在Java中也是尽量不使用嵌套类。其实静态成员类+内部类(含:非静态成员类、匿名类、局部类)=嵌套类。如果要用也最好优先使用静态成员类,内部类最好少碰,尤其是匿名类(但有些地方还必须用它,矛盾呀)。
批注:用惯了Java的人想必也不会要这个“上天所赐”的。仅一个 == 就被MS自己重载成了9中的样子(其实,人家重载得还是很不错的,只是咱们在用的时候头脑不灵光)。你希望像 BigDecimal 这样的值类重载 + - * / 吗?又是 仁者见仁,智者见智了吧?
批注:struct在C#中出现的原因我还真不敢乱猜,从C/C++沿袭而来?还是像MS说的在性能上略微优于class?总之,只要知道在构建值类的时候,可以使用之就可以了。
一个C#集合中可以包含多个public的类或接口,跟文件名没有关系。
批注:MS没有像Sun那样给namespace的命名方法一个官方的建议(Sun建议package的命名法为域名的逆序,均为小写字母)。而且.Net也不要求按目录及文件名保存类(Java最早也没有此要求)。哪种方式更好呢?我想还是一个习惯问题,至少我还是觉得Java的方式更清晰明了。而不少.Net的工程,打开后所有的Source文件都在一个“大平层”,很难受的说。
批注:接口中应该/可以包括常量的定义吗?公说公有理,婆说婆有理。个人认为,即使Java运行,也尽量别这么做。
批注:原作者笔误吧?是否应该是 is ? as 是强制类型转换,和更常见的 变量a = (类型)变量b; 不同的是,如果转换失败as会返回null,而括号式转换回抛出异常。as的语法和AS3语言中是相同的。
批注:这个事实在Java和C#中都是一样的。但是,就接口和抽象类(即使包括骨架类)的选用依据可不是这个,这只是一个表现而已。再有,接口一旦发布了,就是你对外的一种承诺。之后即使是版本升级也不能再做任何改动,哪怕是增加新方法。那非要增加怎么办?如果同时提供的骨架类也控制在你的手里,可以通过在这个骨架类(其实就是抽象类的一种用法,骨架类实现接口,实际类再继承这个骨架类,骨架类中可以为实际类实现一些通用的、或默认的方法)提供一份新增方法的默认实现来达到目的。但这并不是明智的,因为版本升级时需要增加的新方法,往往是一些实实在在的干活儿的方法,在骨架类中给出一个默认实现往往没什么实际意义。更好的做法,是写一个新的接口去继承原来的接口,把新增的方法在子接口中声明。这样可以保持100%向前兼容,需要实现新方法的类属于伴随此次接口升级或日后要取实现的类。
批注:这个也没什么好说的,各家有各家的写法,如果非要说也还是习惯的问题。同上半篇的6。
但是抽象类的抽象方法默认就是一个多态起始点,后续的子类只要override就行了。
批注:感觉还是同上半篇的6。也许是我还没深刻理解?
批注:两个接口如果定义了相同的方法,方法名、参数个数、参数类型、返回值类型、可能抛出的异常(这个C#真没有)都一样的话,那实现它的时候,还区分是来自哪个接口的干吗?有这个必要吗?Java在这里“犯傻”我看挺好。 |
|
来自: woshishenxian... > 《c#》