天天看點

c 和 java 文法對比_c#文法與c++ 及 java文法的對比分析

早期開發的時候一直用c/c++,後來主要用的是java。最近需要用下c#。

熟悉了下c#,發現c#語言在對c/c++基礎上做了很多簡化,同時參考了很多java的文法習慣,本來在文法上c/c++就有很多和java類似的地方,現在c#就類似的地方更多了,不過還是有很多差別。

本文總結下c# 和c++及 java的文法差别,重點比較與java的差別,便于互相學習,加強了解。

一、c#與c++的差別

相比c++,c#做了很多簡化,使的編寫代碼更加容易,重要的變化由如下方面:

1、抛棄了指針的使用。在c#中沒法使用指針了,在對象成員的調用也隻有一種方式,就是通過 . 來引用。

2、完全面向對象。在c#中,不再有全局的函數了。所有的代碼都必須在類中。連基本的基本類型都有方法,如:

classMyapp

{private static void Main(string[] args)

{int a = 10;string value =a.ToString();int b = int.Parse(value);

}

}

3、沒有了頭檔案的概念,類的定義和實作都在類中。

4、引入了命名空間的概念,用于劃分源代碼,類似java的包的概念。

5、類的繼承上廢除了多繼承的概念,一個類智能有一個父類,而在c++中可以有多個父類。

6、引入了類似java中的接口概念。

7、引入了屬性的概念,簡化了對成員變量的操作。

下面我們重點介紹c# 與java的對比。

二、c#與java基本文法的對比

1、程式架構

同java一樣,c#要求所有的代碼都要在類中,不再同c++一樣,既可以定義類,也可以定義全局的方法。

java程式的入口代碼必須是某個類中的如下的方法 :

public static void main(String[] args);

而在c#中,入口方法是

static void Main(string[] args)

注意:c#中Main的第一個字母M是大寫,且Main方法的參數可以不定義。方法的修飾符也可以不加public。

2、包和命名空間

在java中,通過包來組織java源檔案。在c#中,通過命名空間來組織c#源檔案。 它們的含義和作用是類似的。

差別是,java強制要求java源檔案的存放補錄必須與包路徑嚴格一緻。

在java中,通過import引入包,而在c#中通過using引入命名空間。

兩者都可以通過全路徑來引用類(這樣就不需要import和using了)。

3、基本資料類型

兩者大部分基本類型的名稱都一樣,如 int ,char等。枚舉定義的關鍵字都是 enum。數組定義和使用文法也是類似。

典型的差別是:

1)布爾型在java中是 boolean,而在c#中是bool。

2)字元串類型名在java中 是 String ,而在c#中是 string (第一個字母s是小寫)。

最關鍵的是在java中進行字元串内容的比較要用 equlas方法,而在c#中直接可以用 == 比較。

4、語句

兩者的  if 語句,switch語句,for,while, do ...while,break, continue 使用方式都一緻。

有個差別是,在java中,可以用for循環周遊集合。而在c#中需要用單獨的關鍵字 foreach來周遊,但使用方法一樣。

三、c#與java面向對象文法的對比

java和 c# 都是通過 class關鍵字來定義類,也都不需要頭檔案。類的實作代碼用  { }擴起。

1、類的成員

c#中引入了一個屬性的概念。

我們知道在java中,為了提高安全性,我們定義成員變量一搬建議定義private的,這樣為了其它類能通路該變量,再定義相應的get 和 set 方法,代碼如:

classA{private intnum;public void setNum(intnum) {this.num =num;

}public intgetNum() {returnnum;

}

}classB{public voidtest(){

A a= newA();

a.setNum(10);int num =a.getNum();

}

}

而在c#中,為了簡化操作,引入了一個屬性的概念,舉例如下

classA

{public int num { get; set; }

}classB

{public voidtest()

{

A a= newA();

a.num= 10;int re =a.num;

}

}

在類A中,定義了一個屬性 num,在類B中,直接通過屬性名可以通路,簡化了java中的文法。

在A中定義num時,可以隻有get或set标記,表示隻讀或隻寫的。

上面的方式存在一個問題,如果在get或set操作時需要通過一定的計算來傳回值,既可以采用如下的代碼方式。調用方法不變。

classA

{private int_num;public intnum

{get { return_num; }set { _num = value*2; }

}

}

與上面相比,先定義了一個普通的變量_num(這裡是private的,不讓外部直接通路)。

然後定義了一個屬性num,并且有相應的代碼,其中set代碼中的 value是隐式參數,是在給屬性設定值時傳入的參數。

這和java代碼的使用方式類似了,隻是省去了需要定義  setXXX類似的方法。 另外調用時簡化了,直接通過屬性名就可以。

2、通路修飾符

在java中,有 public, protected,private 和 預設四種級别的修飾符,在定義類和成員時不加修飾符,預設是預設的。

在c#中,預設修飾符需要顯示的用internal關鍵字辨別,并且如果定義時不加修飾符,預設不是internal 而是 private的。并且在c#中,可以 protected internal組合使用,其含義是通路僅限于該類或目前程式集(同一命名空間)的派生類。單獨的protected範圍比protected internal大,允許的派生類不限于目前程式集,加上了internal将派生類限制在目前程式集。

3、類的繼承文法

兩者都支援類的繼承,在c++中支援多個父類,在c#中進行了簡化,同java一樣,一個類隻允許有一個父類。

在java中通過extends關鍵字繼承類,在c#中采用的是c++的文法,用 :後跟父類表示。兩者對父類構造函數的處理機制也不一樣。下面舉例說明。

下面代碼是java的例子:

classA{private intnum;public A(intnum){this.num =num;

}

}classB extends A{public B(intnum) {

super(num);//其它代碼,super語句必須放在第一行。

}

}

可以看出,在java中使用extends關鍵字來繼承父類,用 super方法來調用父類的構造函數。

下面是c#的代碼

classA{private intnum;public A(intnum){this.num =num;

}

}classB : A{public B(int num):base(num) {

}

}

可以看出,在c#中是通過 : 辨別符來繼承父類,而且是通過base關鍵字來調用父類構造函數。

4、接口

在java中,引入了接口類型,一個類可以實作一個或多個接口.

在c#中,參考java引入了接口的機制,注意在c++中沒有接口的機制。

但兩者在實作接口的文法上有些差別,在java中通過implements關鍵字來辨別,而在c#中,使用同繼承一樣。

下面是java的文法例子

interfacehello1{}interfacehello2{}classA implements hello1,hello2{private intnum;public A(intnum){this.num =num;

}

}classB extends A implements hello1,hello2{public B(intnum) {

super(num);//其它代碼,super語句必須放在第一行。

}

}

在java中,當一個類同時需要繼承父類和實作接口時,extends語句要放在 implements語句前。

下面是c#的文法例子

interfacehello1 { }interfacehello2 { }classA:hello1,hello2{private intnum;public A(intnum){this.num =num;

}

}classB : A,hello1,hello2{public B(int num):base(num) {

}

}

在 c#中,當一個類同時需要繼承父類和實作接口時,因為都是跟在 : 後面,需要将父類名放在前面,接口名在後面,如上面例子。

5、重載、重寫(多态)

所謂重載,就是一個類可以有多個方法,方法名一樣,但參數資訊不一樣。這個java和 c#都支援。

所謂重寫,是面向對象程式設計中多态特性的展現。就是子類可以定義和父類一樣的方法,具體執行時是執行父類方法還是子類方法,動态根據執行個體綁定。java和c#都有這個特性,差別是使用文法上有些不同。

java的例子:

package com;public classDemo {public static voidmain(String[] args) {

A a= newA();

a.show();//輸出的是 i am A

B b= newB();

b.show();//輸出的是 i am B

A c= newB();

c.show();//輸出的是 i am B. 多态展現,動态決定調用父類或子類方法。因為c實際是指向B的執行個體

}

}classA {public voidshow() {

System.out.println("i am A");

}

}classB extends A {public voidshow() {

System.out.println("i am B");

}

}

可以看出,子類B通過定義相同的方法,重載了父類A的方法。實際執行時,根據變量指向的具體執行個體決定調用是父類或子類的方法。

c#的例子,c#在多态上的文法參考了c++的特點,需要通過virtual和override關鍵字來辨別。

classMyapp

{private static void Main(string[] args)

{

A a= newA();

a.show();//輸出的是 i am A

B b= newB();

b.show();//輸出的是 i am B

A c= newB();

c.show();//輸出的是 i am B. 多态展現,動态決定調用父類或子類方法。因為c實際是指向B的執行個體

}

}classA {virtual public voidshow() {

System.Console.WriteLine("i am A");

}

}classB : A {override public voidshow() {

System.Console.WriteLine("i am B");

}

}

可以看出,在c#中,要想實作繼承的多态性,需要在父類方法中用virtual關鍵字辨別,然後在子類的方法中用override關鍵字進行辨別。

需要說明的是,對于父類定義的virtual或非vritual方法,子類可以不重載,但也可以定義同樣的方法(沒有用override關鍵字),這是允許的,這時子類的該方法将隐藏父類的方法,這個不是動态的特性。

6、抽象類和抽象方法

有時在父類中定義一個序方法,但該方法在基類中不需要有具體的實作,需要在子類中實作。這個特性java和c#都支援。

隻是文法上有細微差别。這裡舉例說明下。

java的例子:

package com;public classDemo {public static voidmain(String[] args) {

B b= newB();

b.show();//輸出的是 i am B

A c= newB();

c.show();//輸出的是 i am B. 多态展現,動态決定調用父類或子類方法。因為c實際是指向B的執行個體

}

}abstract classA {public abstract voidshow();

}classB extends A {public voidshow() {

System.out.println("i am B");

}

}

在java中,是通過abstract關鍵字辨別抽象類和抽象方法的,具體有如下細節:

1)一個類有抽象方法,其所在的類必須定義為抽象類。

2)子類繼承抽象父類,要麼實作父類的抽象方法,要麼繼續把自己定義為抽象類。

3)抽象方法沒有方法體。抽象類不能執行個體化。

下面是c#中的例子

classMyapp

{private static void Main(string[] args)

{

B b= newB();

b.show();//輸出的是 i am B

A c= newB();

c.show();//輸出的是 i am B. 多态展現,動态決定調用父類或子類方法。因為c實際是指向B的執行個體

}

}abstract classA {abstract public voidshow();

}classB : A {override public voidshow() {

System.Console.WriteLine("i am B");

}

}

除了子類方法定義需要加override關鍵字,其它文法要求與java一樣。另外對抽象類和抽象方法的要求也與java中的要求一緻。

四、c#與java其它對比

1、常量和隻讀字段

在java中,可以通過final來定義隻讀變量,可以使成員變量,可以是方法的内的局部變量,也可以是形參。并且定義和初始化可以一起,也可以分開。

如果是定義的的final成員變量,則需要在構造函數中初始化。 如果是方法内的局部變量,可以在定義後指派。

在c#中,可以用 const關鍵字定義常量,要求必須在定義時了解指派。

在c#中,還可以用 readonly來定義類的成員(注意不能定義局部變量),可以在定義時指派,也可以定義時不指派,而在構造函數中指派。

2、異常處理

java和 c#有類似的異常處理機制和文法,都有  try, catch, finally, throw 這幾個使用關鍵字。 差別是:

1)java中的異常分為檢查時異常和運作期異常兩種,而c#中隻有一種(運作期異常)。

2)在java中 ,catch語句必須帶異常類型參數。

而在c#中,可以不帶,表示是預設的,表示對所有異常處理,但如果定義了多個異常,不帶參數的必須放在最後。

3、參數傳遞

在java中,參數傳遞隻有值傳遞一種方式。對于基本資料類型,如 int等,在方法内無法修改方法的值。

而在c#中,保留了c/c++的特性,通過 ref 和 outer 關鍵字,可以讓形參和實參指向同樣的值,這樣在方法内修改形參的值,方法外的實參值也跟着變化。

不過,為了提高程式的可讀性,建議少用這種特性。

4、内部類

在java中,支援内部類,包括匿名内部類。但在c#中,支援内部類,但不支援匿名内部類。

如下面的匿名内部類在java中是允許的,但在c#中是不行的。

package com;public classDemo {public static voidmain(String[] args) {

A a= newA() {public voidshow() {

;

}

};

a.show();

}

}abstract classA {public abstract voidshow();

}

5、分部類

在c#中,編寫代碼時可以将一個類的定義分到多個cs檔案中,後續由編譯器自動合并。這個在java中不支援。

這個特性感覺很不好,強烈建議正常情況下不要使用。