淺談C# vs Java (1) (轉)

gugu99發表於2008-03-01
淺談C# vs Java (1) (轉)[@more@]

CLR vs JVM:namespace prefix = o ns = "urn:schemas--com::office" />



1.概念



Microsoft一直在宣稱CLR(公共語言執行環境)是所謂得虛擬機器而並非JVM虛擬



機的概念。這是由於CLR將支援一切遵循CTS(公共語言規則)的語言在其上執行並且互不干擾,從這個概念上說CLR相較JVM來說更像一個平臺。



 



2.編譯



  將原始碼編譯成為.class,透過java命令來執行。例如:



  java test.class



  而則將原始碼編譯成為.exe檔案。但這個exe檔案不同於傳統的exe檔案,它是由一個清單和MSIL(Microsoft中間語言)程式碼組成。格式大致如下:



    PE(-Portable executable)頭 --- exe檔案頭



  清單 --- 檔案中所包含的型別和類



  跳轉命令 --- 跳轉到MSIL直譯器



  MSIL程式碼



從以上的結構可以看到,C#同Java一樣能夠輕鬆被反編譯,不同的是,Microsoft還提供了用於讀取編譯後MSIL的工具ildasm。



另外,雖然Microsoft對這種結構提出了種種的好處,但是如果把MSIL看成是Java編譯後的程式碼(即.class檔案中的程式碼),那麼C#的檔案結構更象是把Java的執行命令和.class檔案已exe檔案的方式封裝起來。如下表:











C#





Java







PE頭





-







清單





關於這點將在部署一節中論述







跳轉命令





java命令







MSIL程式碼





.class檔案



分析了C#編譯結果,就會發現C#並沒有因為編譯成了可檔案,就依附於window平臺。從理論上說,如果有一個版的MSIL直譯器(實際上它是CLR的一部分)和一個Linux版的C#的,那麼就可以將window下編寫的C#的程式碼在Linux下重新編譯,於是就實現了所謂“處處編譯,處處執行”。而在這工程中,保持程式碼編譯一致性的CTS(公共語言規則),難怪有自由組織曾提議使用Microsoft的CLR&CTS構架來統一當前自由軟體界的編譯環境。



 



3.執行



  Java早期是一種解釋性語言,後來為了提高採用了JIT(just-in-time)技術,還有一些工具可以將Java生成特定的的二進位制程式碼。



  而C#也必不可少的選用了MSIL和JIT的機制。根據不同的情況可分為3類:



a)  時程式碼生成(Install-time code generation):將當前程式碼完全編譯成特定的CPU的二進位制程式碼。之所以叫做安裝時程式碼生成,是因為這個編譯過程是在安裝時進行的。



b)  JIT:與Java的JIT方式相似。



c)  EconoJIT(經濟性JIT):與JIT不同的是,它透過丟棄已產生出的,編譯過的程式碼回收,比較適用於少量記憶體的手持裝置。



4.部署



  Java採用的是將包路徑和目錄相對應的方法,生成一層一層的目錄。之後又推出使用jar檔案封裝的方式。



C#採用的是後設資料紀錄的方法。所謂後設資料就是上文C#編譯結果結構中提到的“清單”。C#透過後設資料紀錄型別和類的資訊,相較Java的目錄結構和jar檔案方式,封裝性提高



了不少。不過目錄結構有一個好處是顯而易見,就是當有部分程式碼需要修改的時候,只要重新編譯需要修改的程式碼,並覆蓋相應的類就可以了。



 



一切都是



C#和Java都宣稱自己的一切都是物件,但是真正實現這一說法的恐怕只有SmallTalk。



這主要是因為將基本資料型別描述成物件所造成的程式碼方面的降低是很難讓人接受的。於是C#和Java都提出了關於這一問題的解決方案。



  Java保留了基本資料型別,併為每一種型別提供了一個對應的類,如int型對應Integer類, long型對應Long類。當需要用類來描述基本資料型別時,即可透過生成其對應的類,如下程式碼:



  int n = 5;



  Integer in = new Integer(n);



  使用後,又可以將對應類的值賦給基本資料型別,如下程式碼:



  Integer in = new Integer(5);



  int n = in.intValue();



  相對應的,C#也採用了為基本資料型別提供對應類的方式,但在使用上採用的是開箱(unboxing)和裝箱(boxing)操作。所謂裝箱就是將基本資料型別轉換為對應類。而開箱的作用剛好相反。



當試圖將基本資料型別以一種與System.基類介面相匹配的方式使用時,將自動將它裝箱,使之能夠像一般物件一樣被使用。如下程式碼:



int n = 42;



Int32 in = n;



開箱的程式碼如下:



int n = 42;



Int32 in = n;



//注意:開箱時必須進行顯示的型別轉換



int n2 = (int)Int32;



有以上的例子可以看出,在一切都是物件的問題上,C#和Java的解決方式是很相似,



只是C#封裝了更多的操作細節。但是是否有系統來做這些操作可以提高語言本身的效率呢?Microsoft的回答肯定是肯定的。



 



小結



  以上對C#和Java在編譯執行以及物件的設定等問題上作了比較,從中發現,C#在設計上大量模仿Java,但在具體實現上C#封裝了更多的細節,相較Java來說應該更易於使用,這大概是Microsoft的風格吧。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1000227/,如需轉載,請註明出處,否則將追究法律責任。

相關文章