国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

讀《C# 和 Java 的比較》有感

2019-11-17 02:58:48
字體:
來源:轉載
供稿:網友
讀《C# 和 java 的比較》有感

網上的一篇《C# 和 Java 的比較》(或者叫《Java 和C# 的比較》)寫的挺不錯的,今天忽然搜索到。

自己剛剛接觸C#,也不由自主地隨時都拿來和Java做對比,所以就心血來潮在原作者的每一條之后斗膽都寫了些文字。就當是給自己再加深一遍印象吧。

【非常抱歉,由于網上此文章已經被轉載多次,所以真的找不到原出處了,所以沒法貼出作者原貼的連接】

開始吧...

2007年11月1日 1。訪問控制方面:C#有public、internal、PRotected、private,比java多了個internal,其實它跟java的包訪問差不多,internal表示同一個編譯集合(如exe、dll)下的類可以互訪。 對于protected,java和C#有區別。在java中,protected和包訪問級別差不多,即不是私有的。而在C#中,protected和private差不多,即它標志的成員是私有的。 有這樣一種情況:類中的一個成員,需要它能被子類訪問到,同時能被同一個集合中(無論是java的包還是C#中的編譯集合)的其他類訪問到,怎么辦呢?在java中,只要用protected就行了。在C#中,可以同時指定internal protected(二者的順序隨意)。 在有這樣一種情況:類中的一個成員,需要它能被子類訪問到,但不能被同一個集合中(無論是java的包還是C#中的編譯集合)的其他類訪問到,怎么辦呢?在C#中,可以指定protected(二者的順序隨意)。但java就無能為力了。

評論:我很喜歡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# : static [類名]{} java :static{}

批注:原來是這樣寫,我找了半天也沒搜到C#中的靜態代碼段如何個寫法,如今得來全不費工夫。

3。Java中的main函數必須是public static void main(String[] args)的樣子,否則虛擬機拒絕運行。C#中,Main函數可以是private的(甚至可以是protected),可以沒有參數,可以返回int值。有點像C語言。 4。發現csc.exe有一個功能很好,100后面加一個小寫的L,它會警告:“l”后綴容易與數字“1”混淆;為清楚起見,請使用“L”。

批注:MS的人性化關懷呀。

5.C#提供了一種機制,使得某個變量可以被動態賦值一次,以后就不能再改了。那就是readonly關鍵字的功能。

批注:這個機制可能在特定場合下很有用。比如:抽簽,這樣你就不能耍賴了。

6.java在繼承、多態方面,比C#強多了。Java默認的多態,C#要求加上virtual(被繼承的方法)和override(繼承的方法),而且C#要求不能改變原來的訪問修飾符,不像java那樣,可以指定更加寬松的訪問方式。如果有人利用C#來寫程序,必須經常帶上virtual和override,還必須照抄原來的訪問控制符,不會很郁悶嗎?難道有人用C#的面向對象特性時,會舍棄多態的特性?這會引起多大的混亂啊。 多態是面向對象的精髓,像java那樣默認不是更好嗎?

批注:C#號稱和Java有90%的相似性,但它必將是從C++發展而來的,在虛函數的概念上還是延續著C++的方式。習慣了Java之后,真的是感覺別扭。Java多好:默認情況下都是虛函數,允許被子類重寫,但是對于有意不想讓子類重寫的方法用final關鍵字來修飾。

7. C#中new還可以用來指定子類的某個方法要隱藏父類的具有相同簽名的方法。這是不是多余的?你不用也可以,不過csc.exe會警告你,如“lan.Other.Main(string[])”隱藏了繼承的成員“lan.HelloWorld.Main(string[])”。如果是有意隱藏,請使用關鍵字 new。 像java那樣默認多好啊。 但是話又說回來,C#這樣做也是有原因的。如果類B繼承了類A,B接下來有添加了一個方法叫做hi(),那是B特有的。然后類A(假設是別人來維護的,你不能看到源碼)突然也增加了一個方法hi()。如果B自己那個hi()跟A那個hi()的返回值不一樣,當你更新類庫A后,可能導致程序運行錯誤或不能編譯。C#就很好就地避免了這種問題。(雖然這種問題出現的概率挺小的…)

批注:其實這個還是和6有關,總之對于Javaer來說就是兩個字“別扭”。那些非虛函數干脆就不允許改寫就得了,像Java的final那樣。干嘛“既要做婊子又要立牌坊”呀,當警告超過一定數量時,估計就掩埋了,不容易被注意到。而真等到了使用的時候,哪一個是多態?哪一個是“另起爐灶”?使用者不暈菜才怪呢!

8.C#中,防止一個類被繼承,要用關鍵字sealed。而定義一個常量時,要用const。 像java統一用final多好啊。

批注:這倒沒什么,關鍵字都一樣了,顯得人家MS多沒水平嗎。我們只是需要再多記住一些東西就是了,多無奈呀。

9.在C#中,要比較兩個引用變量是否指向同一個對象,不能用java中的= =,而要用Object里的ReferenceEquals方法。C#中,不能用一個類的實例去調用該類的類方法,必須用類名。所以java中的o1= =o2等價于C#中的Object.ReferenceEquals(o1,o2)。

批注:都是操作符重載惹的禍。Equals就是Equals;ReferenceEquals就是ReferenceEquals。但 == 可要注意了,有的時候是 Equals 有的時候是 ReferenceEquals。== 被重載了,我反而更不敢用了,還是稍微費點事寫 Equals 和 ReferenceEquals 吧,即不會犯錯誤,有意義清晰。

10.C#中沒有原始類型的包裝類,但是也提供自動裝拆箱的功能,和java有的一樣。區別是,C#的裝箱是自動的,拆箱就要強制轉換了。 int i=100; object obj=i; i=(int)obj; 具體怎么裝和拆,我們不知道。只知道CLR將int轉換成object了。

批注:包裝類還是有的吧?如:int -> Int32;string -> String;甚至 object -> Object。是我的理解有誤嗎?至少從VS中關鍵字高亮的顏色就能區分開。

11.java的內部類有時候幫助很大。到了C#那,就只提供靜態的內部類了。這意味著外部類只相當于是一個命名空間而已。C#中的內部類能訪問外部類的私有成員,這可能會讓它有點用。

批注:這一點我沒什么研究,在Java中也是盡量不使用嵌套類。其實靜態成員類+內部類(含:非靜態成員類、匿名類、局部類)=嵌套類。如果要用也最好優先使用靜態成員類,內部類最好少碰,尤其是匿名類(但有些地方還必須用它,矛盾呀)。

12.C#中雖然有運算符重載,但是為了整個.net的一致性,應該不會鼓勵使用。因為有的.net語言沒有運算符重載,而.net的一個目標就是消除各種語言的差別。

批注:用慣了Java的人想必也不會要這個“上天所賜”的。僅一個 == 就被MS自己重載成了9中的樣子(其實,人家重載得還是很不錯的,只是咱們在用的時候頭腦不靈光)。你希望像 BigDecimal 這樣的值類重載 + - * / 嗎?又是 仁者見仁,智者見智了吧?

13.C#多了一個struct值類型,它就跟原始類型一樣。微軟在必要的時候會幫你將struct封裝成Object,就像封裝int類型一樣。以至于你可以認為struct也是由Object繼承而來,雖然struct本身并不支持繼承。(struct可以不用new來初始化,但它里面的內容必須初始化后才能調用其方法;struct沒有析構方法;struct沒有默認的構造方法)。

批注:struct在C#中出現的原因我還真不敢亂猜,從C/C++沿襲而來?還是像MS說的在性能上略微優于class?總之,只要知道在構建值類的時候,可以使用之就可以了。

2007年11月2日 1.java中類的訪問控制符只能是public,或者沒有(即默認的包訪問)。但是C#中,class和interface的訪問控制符可以是public / private / internal / protected / internal protected。當然你必須先取得對類的訪問,才可能訪問到類的成員。

一個C#集合中可以包含多個public的類或接口,跟文件名沒有關系。

批注:MS沒有像Sun那樣給namespace的命名方法一個官方的建議(Sun建議package的命名法為域名的逆序,均為小寫字母)。而且.Net也不要求按目錄及文件名保存類(Java最早也沒有此要求)。哪種方式更好呢?我想還是一個習慣問題,至少我還是覺得Java的方式更清晰明了。而不少.Net的工程,打開后所有的Source文件都在一個“大平層”,很難受的說。

2.C#中的接口不能包含常量,而java可以。

批注:接口中應該/可以包括常量的定義嗎?公說公有理,婆說婆有理。個人認為,即使Java運行,也盡量別這么做。

3.C#中的as和java中的instanceof功能一樣。但C#提供一個據說是效率更高的as關鍵字。

批注:原作者筆誤吧?是否應該是 is ? as 是強制類型轉換,和更常見的 變量a = (類型)變量b; 不同的是,如果轉換失敗as會返回null,而括號式轉換回拋出異常。as的語法和AS3語言中是相同的。

4.接口和抽象類在C#和java中都差不多,這里提一下接口設計和抽象類設計的區別之處。如果你更改了一個接口的設計,比如增加了一個方法,使用你以前的代碼的用戶將不得不改變他們的代碼,否則不能運行和編譯。但是如果是一個抽象類,你可以提供一個含默認實現的方法,用戶的代碼則不需要改變。

批注:這個事實在Java和C#中都是一樣的。但是,就接口和抽象類(即使包括骨架類)的選用依據可不是這個,這只是一個表現而已。再有,接口一旦發布了,就是你對外的一種承諾。之后即使是版本升級也不能再做任何改動,哪怕是增加新方法。那非要增加怎么辦?如果同時提供的骨架類也控制在你的手里,可以通過在這個骨架類(其實就是抽象類的一種用法,骨架類實現接口,實際類再繼承這個骨架類,骨架類中可以為實際類實現一些通用的、或默認的方法)提供一份新增方法的默認實現來達到目的。但這并不是明智的,因為版本升級時需要增加的新方法,往往是一些實實在在的干活兒的方法,在骨架類中給出一個默認實現往往沒什么實際意義。更好的做法,是寫一個新的接口去繼承原來的接口,把新增的方法在子接口中聲明。這樣可以保持100%向前兼容,需要實現新方法的類屬于伴隨此次接口升級或日后要取實現的類。

5.C#中一個類實現一個接口時,它的相關方法不必指明override;但一個類繼承一個抽象類的抽象方法時,必須加上override,否則視為隱藏。(事實上,只有抽象方法或者是virtual、或者是接口方法才能被覆蓋即override。不能無緣無故地override。)

批注:這個也沒什么好說的,各家有各家的寫法,如果非要說也還是習慣的問題。同上半篇的6。

6。C#中存在一個“多態起始點”的問題。如果一個類實現了接口的某個方法,只是接口到該類才有多態的功能,若要這種多態繼承下去,該類必須指明是virtual,多態起始了,接下來的子類提供override就能多態了,不需要更多的virtual。

但是抽象類的抽象方法默認就是一個多態起始點,后續的子類只要override就行了。

批注:感覺還是同上半篇的6。也許是我還沒深刻理解?

7.當一個類實現了兩個接口,兩個接口有一個相同的方法定義,C#有一種解決機制,叫做顯示實現。Java干脆就不處理這種情況,反正實現之后就能調用了,不必指明是哪個接口的,留給程序員自己考慮。 當然C#中的顯示實現還有其他功能。舉個例子,接口A有一個方法叫做f(),類B實現了A。按理說B的實例就能自由調用f()了,但是如果有這樣的要求:B的實例只有被cast成A之后才能調用f()。在java中,這樣無理的要求是不允許的。但是C#可以做到,就是通過顯示實現的方式。有誰會使用這樣的特性?

批注:兩個接口如果定義了相同的方法,方法名、參數個數、參數類型、返回值類型、可能拋出的異常(這個C#真沒有)都一樣的話,那實現它的時候,還區分是來自哪個接口的干嗎?有這個必要嗎?Java在這里“犯傻”我看挺好。

推薦個文章:從海底撈的火鍋和路邊的煎餅談談用戶體驗


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 汤原县| 甘泉县| 精河县| 乐陵市| 台北市| 全椒县| 浑源县| 齐河县| 华亭县| 常山县| 吉安市| 南靖县| 休宁县| 米脂县| 四会市| 芜湖市| 定州市| 东莞市| 鞍山市| 象州县| 敖汉旗| 金溪县| 尖扎县| 通化市| 平阴县| 长汀县| 白城市| 连山| 沁源县| 行唐县| 固镇县| 根河市| 巴中市| 荆门市| 广安市| 监利县| 朔州市| 泰来县| 南城县| 浑源县| 民勤县|