C#與Java的比較

這篇文章對C#與Java作一個語言級的對比,方便C#轉Java或Java轉C#的人有個大體瞭解。
這裏大體用C#3.0與Java6.0作比較。

寫完後得知維基百科裏有更加全面得多的比較:

 

 

.NET(C#)   Java
 
基本類型   基本類型
C#中有無符號數,Java沒有。

C#中有值類型,且可本身定義值類型的結構體(struct)。
Java中的基本類型(或叫基元類型)即爲值類型,但Java沒有結構體,因此不能自定義值類型。
C#中的值類型(包括全部基本類型)間接繼承自Object,有本身的方法能夠調用;Java中的值類型(即基本類型)不繼承自Object,只是簡單的數據,沒有方法能夠調用。

C#中int等同於System.Int32,是值類型;bool等同於System.Boolean;等。
Java中int是基本類型,是值類型,而Integer是引用類型,Integer是int的包裝器,int自身沒有方法,Integer有一些方法;int與Integer之間可隱式轉換(致使裝箱和拆箱),但當Integer值爲null的時候會在運行時拋出異常。boolean等相似。

Java中的int與Integer的對應在C#中相似int和Nullable<int>的對應,它們的後者都是前者的包裝,且後者能夠等於null。但Nullable<int>實際上仍然是值類型的(因此仍然很輕量級),因此從內存上講C#中int和Object的對應更接近Java的對應一些。C#中Nullable<int>到int的轉換必須顯式進行,由於Nullable<int>中的值爲null時會引起運行時異常。
其餘基本類型與之相似。
 
 
委託,事件  
[無]
C#中的委託能夠認爲是方法的類型化,因而能夠將方法放在變量裏傳遞。事件是對委託作了一層包裝。
Java經過接口來實現C#中委託和事件的功能,可經過匿名類來達到C#中匿名委託的做用(一樣也能實現閉包的功能)。
另,C#中也有匿名類,但C#中的匿名類只有數據沒有方法。
 
 
非託管  
[無]
C#能夠有非託管代碼,能夠有指針等。Java沒有。
 
 
索引器  
[無]
C#有索引器,可方便容器類實現相似數組的效果。Java沒有,Java的容器基本上用put,get,set等方法達到一樣效果。
 
 
屬性  
[無]
C#的屬性經過在內部定義get/set方法,使外部使用時像是在使用變量字段,但實際上是在調用get/set方法,以達到透明的封裝數據的目的。
Java沒有屬性的概念。Java經過約定爲字段XX添加getXX,setXX方法達到一樣的目的。
 
 
預編譯指令  
[無]
C#有預編譯指令可方便調試,且有ConditionalAttribute來描述方法。Java沒有。
 
 
操做符重載  
[無]
C#可重載操做符。Java沒有。

Java本身重載了String的+和+=,但沒有重載==,這是我這段時間犯的最多的錯誤。C#中String的==是比較值相等,Java中==是Object的默認行爲:比較引用相等,要比較值相等得用equals方法。(這麼多年編程以來,我彷佛曆來沒有遇到過要比較兩個字符串變量的引用相等。對於比較值相等來說,==符號比equals方法調用看上去優雅得多,何況方法調用還得注意空指針的狀況)
 
 
內部類   內部類
Java的內部類能夠直接訪問外部類的實例成員。
C#的不行。C#的內部類等同於Java的靜態內部類。
 
 
goto、switch   [goto]、switch
C#容許用goto。Java的goto是保留關鍵字,不能使用。但Java容許有標籤,在有嵌套循環時能夠在continue、break後面跟標籤名。

C#的switch可使用long、String;Java不能夠。

Java的switch中的case子句在後面沒有跟break的狀況下直接跳到下一個case子句;
C#中只有在前一個case沒有任何代碼的狀況下才容許不寫break直接跳到下一個case,C#中能夠經過goto跳轉到另外一case。
 
 
enum   enum
C#中的枚舉是值類型,且其基於數值類型(默認基於int),可設置枚舉項對應的數字,不能在其中添加方法等任何其餘成員。
Java中的枚舉是引用類型(Java除了基本類型外,任何類型都是引用類型),不是基於數值類型。除了不能繼承外,它跟普通類差異不大,能夠添加成員方法和成員變量等(固然也就能夠重寫toString方法)。

C#和Java的枚舉均可以用於switch。

能夠將C#的枚舉做爲數值看待而直接進行位運算,所以能夠在一個變量中存儲多個位標記。
Java的枚舉跟數值沒有直接關係,所以不能直接這麼用。Java用EnumSet來存儲枚舉標誌,不須要直接使用位運算,更遠離底層。
 
 
override   @Override
C#能被重寫的方法必須添加virtual關鍵字聲明爲虛方法,派生類重寫子類方法時添加override關鍵字。
Java默認方法均可被重寫,派生類和子類方法簽名同樣時被認爲是重寫。要聲明不能被重寫的方法需在方法前加final關鍵字。重寫時能夠在方法前添加標註(即C#中的定製特性)@Override,這樣一旦此方法找不到被重寫的方法時編譯器會報錯,以防止拼寫錯誤。
 
 
定製特性   標註
C#用中括號[]將定製特性括起來。Java用@打頭,後面跟定製特性的名字。
 
 
泛型   泛型
Java中泛型實現使用的擦除機制,爲類型參數傳入類型並不致使新類型出現,即傳入了類型參數後在運行時仍然徹底不知道類型參數的具體類型,它的目的是爲了兼容非泛型(因此能夠在泛型和非泛型之間隱式轉換,會有編譯警告但不會有編譯錯誤,這固然其實並不安全);這同時衍生了一系列問題:不能定義泛型類型參數的數組如T[],不能經過new T()的方式實例化泛型,等。
Java的泛型不支持值類型(使用的話會被自動包裝成引用類型)。
 

C#的泛型在類型參數傳入類型後會產生一個新類型(雖然CLR的優化機制會使引用類型共享一樣的代碼),能夠在運行時獲得類型參數的類型信息。能夠定義泛型數組,能夠添加約束使其能夠new。C#的泛型可使用值類型(不會被裝箱)。

對於Java的泛型,簡單的講,它的好處只在編譯時,運行時沒有任何泛型的意義。當你在使用已有的泛型類時,這一般能知足要求;但若是你要本身定義泛型類,那你得知道它有多少你以爲它應該能夠但事實上不能夠的事情。
 
 
 
參數引用傳遞   [無]
C#容許使用關鍵字out,ref顯式指定參數傳遞方式爲引用傳遞。
Java只有值傳遞。
 
 
@字符串   [無]
C#在寫字符串時能夠在引號前加個@符號來取消/的轉義做用。
Java沒有。
 
 
??   [無]
C#的??二元操做符當前面的表達式不爲null時返回前面表達式的值,前面表達式爲null時返回後面表達式的值。
Java沒有。
 
 
using   import
C#能夠用using爲命名空間或類指定別名。(using還有Dispose的使用方式,與命名空間無關)
Java的import能夠引入類或包(即C#的命名空間),static import能夠引入類的成員。
 
 
初始化   初始化
C#調用基類構造函數的語法爲:
SubClass() : base() { }
Java調用基類構造函數的語法爲:
SubClass(){
   super();
}
C#和Java均可以用相似的語法調用同一個類的其餘構造函數。(分別將base和super換成this)

Java有代碼塊概念,會在構造函數以前執行(基類的構造函數以後)。

在成員變量聲明時賦值,Java容許其賦值表達式中引用前面聲明的另外一個變量,如:
private int x = 1;
private int y = x + 10;
這裏變量y的賦值語句有變量x。
C#不容許這樣作。
 
 
interface   interface
Java的接口內容許有內部類、靜態字段等。
C#不容許。
 
 
readonly,const   final
C#的const是絕對的常量,必須在聲明語句中同時賦值,只有數值、枚舉和String能夠聲明爲const。const的值會內聯到各個使用的地方。
C#的readonly表示變量在構造函數執行完以後是不能再變化的。它只約束變量自己,而沒法約束變量引用(若是它是引用類型或者有成員是引用類型)的對象。

Java中的final(在約束變量的時候)看上去更像readonly。
但C#的readonly和const有個區別,readonly的int是不能做爲switch的case語句的,const的能夠。
而Java的final則是:有時候能夠有時候不能夠----編譯時能夠獲得明確值的能夠,反之不能夠。如:
final int x = 1;   // 這個能夠
final int y = new Random().nextInt();   // 這個不能夠
那麼能夠理解爲:編譯時能獲得明確值的時候,final等同於C#的const;編譯時沒法獲得明確值的時候,final等同於C#的readonly。
 
 
[無]   throws
Java在可能拋出異常時,除了RuntimeException(包括派生類),都要麼捕獲,要麼在方法聲明中用throws關鍵字聲明出來表示繼續拋出。
C#沒有采用這種強制處理機制。
 

 

 
功能相同但語法有差別的
namespace == package (Java的package對文件結構也有要求;C#沒有)

internal == [默認] (Java中不寫訪問修飾符即表示訪問權限是package;C#默認是private。C#的internal protected在Java中沒有。)

lock == synchronized (Java中synchronized能夠修飾方法,C#能夠用定製特性[MethodImplAttribute(MethodImplOptions.Synchronized)]達到一樣效果)

 : == extends,implements

base == super

is == instanceof (C#有as,Java沒有)

typeof == .class

[SerializableAttribute]定製特性 == Serializable接口

[NonSerializedAttribute]定製特性 == transient

params == ... (可變數目參數)

 

 




這個列表裏,Java比C#更漂亮的地方基本上只有一處:枚舉。Java的枚舉更高層一些,更靈活。但內存代價比C#的枚舉要高,這可能就是Android裏仍然使用常量而不是枚舉的緣由吧。
因此就從此次比較來說,C#幾乎完勝Java,而C#的新特性像完美的類型推斷、動態編程特性、Lambda表達式、LINQ等等這裏都沒有列入比較。
固然,.NET和Java兩大致系的比較,語言只是一個方面,還有平臺、IDE、開源等其餘不少方面,這裏就不說了。
相關文章
相關標籤/搜索