1. 程式人生 > >C#和java之間的一些差異與共性

C#和java之間的一些差異與共性

C#與java之間的一些共性和差異整理

隱藏:
與java中的重寫幾乎一致,但是需要新增new關鍵字讓編譯器知道,否則會有警告


虛方法:
1.宣告為virtual的方法就是虛方法,在子類中使用override進行重寫,當程式發現該方法是虛方法時,會去尋找子類中是否重寫了該方法,如果被重寫了,那麼就呼叫子類中的方法,所以重寫是多型實現的一種重要的方式,也稱為動態繫結,而過載則是在程式編譯階段就進行的,所以叫靜態繫結,也是編譯前繫結
2.重寫虛方法必須具有相同的可訪問性,基類中的虛方法不能是private的
3.不能重寫static方法或者非虛方法,覆蓋使用的是new關鍵字。而非override
4.方法、屬性、索引器、事件都可以用虛方法或者重寫
5.與java中的抽象方法類似,但是虛方法可以擁有方法體,同時不一定要被重寫,抽象方法則必須被重寫


欄位和屬性:
1.通過設定屬性的方式,來創造類似javabean中的set和get方法、
屬性是public的。欄位是private的,屬性的名稱要自己設定,但是最好和欄位名字要相近,首字母大寫,同時屬性的資料型別和欄位的資料型別要一致,可以使用CTRL+R+E的方式進行快捷封裝。


2.將set屬性刪除,就可以讓屬性成為只讀屬性,對欄位進行保護,get可以獲取欄位的值。set和get類似於java中的方法,可以在set方法中對屬性的值進行檢查,過濾,防止一些不合理的資料出現。


值型別和引用引用型別(值傳遞和引用傳遞):
1.基本資料型別,int bool char double等為值型別,是儲存在棧中的(記憶體),當作用域結束時銷燬,所以儲存速度快
,對於值型別,有關賦值等相關的操作是copy了一份值的副本,因而其中一方更改不會影響到另外以防,例如A=1 B=A 修改A的值和B的值互不影響,各自進行管理,


2.引用型別: 類(String型別屬於類),陣列,介面等物件,就是引用型別,它們是儲存在堆中的(物理硬碟),所以速度會較慢,但是他們的賦值操作,是會互相影響的。 例如: Dog dog=new Dog();    Dog dog2=dog; 這裡的操作是建立了一個dog物件,同時將這個物件賦值給了dog2引用。
這裡的dog 和dog2 是物件的引用,是儲存在棧中的, 而new Dog()這個真正的物件中包含的資料是儲存在堆中的。
所以dog和dog2指向的是同一個物件,因而如果dog或dog2對這個new出來的dog物件進行了修改,那麼dog和dog2在呼叫其中的屬性的時候,都是呼叫的修改後的屬性。 


例子:可以理解成,兩個小朋友一人有一個棒棒糖(值型別),各自吃各自的,自己的吃
完了。對方的不一定吃完。   然後兩人各有一個遙控器,都能對電視機進行控制,當一個人切到了天線寶寶的節目的時候,另外一個人看到的也是天線寶寶,即引用傳遞修改的是同一個東西,而值傳遞修改的是兩個東西,是各自的副本


結構和類:
1.結構中的欄位不能有初始值,類中的欄位可以有初始值,結構中的欄位可以和類一樣有屬性,結構和類都能有構造方法,但是結構中不能有顯式的無參構造方法,可以有帶參的構造方法,同時要為結構中的所有欄位賦值,如果有一個沒有賦值,都會報錯。
  類中則無參帶參都可以有,同時沒有必須為所有欄位賦值的限定。


2.結構可以不必例項化,直接就能訪問它的屬性和方法。 類則不能。 


3. 結構不支援繼承,類支援繼承,編譯器會自動定義結構的無參構造方法


列舉型別:屬於值型別,在列舉中不能定義欄位屬性和方法,列舉是從0遞增的增數值,
限定了某些型別的取值範圍,例如性別。可以防止錯誤的輸入
賦值:列舉名.列舉中的屬性名  例如 Gender.男 或者使用強制型別轉換(Gender)0


引用傳參和值傳參(引用傳遞和值傳遞):
1.按引用傳參,方法修改形參,通常實參也會被修改,
2.按值傳參,方法修改形參,實參不會被修改


ref關鍵字:
新增ref關鍵字,可以讓至傳遞的值型別變數,轉化為按引用傳參,但要注意在傳遞的雙方都要帶上ref修飾(宣告和呼叫時),同時屬性不允許作為ref關鍵字修飾的引數,所以需要單獨宣告一個變數來儲存屬性的值。


out關鍵字:
用來獲取結果。可以視作return的補充。


呼叫順序:
1.先例項化父類中的成員----然後呼叫父類中的建構函式---然後呼叫子類中的例項成員----然後呼叫子類的建構函式
2.使用base()可以進行顯式的呼叫父類的建構函式,使用this()則呼叫當前子類自己的建構函式,括號中可以帶參也可以是無參的


抽象類和抽象方法:
與java基本類似,抽象成員必須是方法屬性時間索引器,


密閉類和密閉方法:
sealed修飾,作用類似於java中的final,如果要修飾變數,則使用const


介面:
與java的語法規則基本一致,但是在繼承了一個類同時實現多個介面的時候,必須將繼承的類擺在:的最前面一個


靜態成員,靜態類:
1.靜態成員不能訪問例項成員因為例項成員需要new出物件以後才會被建立,所以例項成員可以訪問靜態成員,靜態成員無法訪問例項成員


2.靜態類不能建立例項,也不能被繼承,可以定義一個靜態的建構函式,主要應用於基礎類庫,和擴充套件方法


如何擴充套件方法:
如果有原始碼,直接新增新的方法。
如果不能修改,但也不是密閉類,可以通過子類來進行擴充套件
如果以上操作都無法實現,則可以使用靜態類進行擴充套件
1.擴充套件方法所屬的類必須是一個靜態類,2.同時該方法本身也必須是一個靜態方法
3.擴充套件方法的第一個引數型別必須是this+類名
例子:   static class Guid{
             static public void HowTo(this Dog dog){


                }
       
          } 
最後直接通過 Dog dog =new Dog();
           dog.howTo();
就可以對擴充套件的方法進行訪問了,類似於這個方法就是原生在Dog類(需要被擴充套件額外方法的類)中的。


自定義轉換:
1.隱式轉換必須是靜態的公共方法並且使用 implicit operator關鍵字
: public static implicit operator Cat(Dog dog) 
{  
         return new Cat();
  }
括號外的物件是傳入的引數是想要被隱式轉換後的物件型別


2.顯式轉換與隱式轉換的定義基本一致,差別在於使用explicit關鍵字
: public static explicit operator Dog(Cat cat)

         return new Dog();
 }
 括號外的物件是傳入的物件想要被顯式轉換後的物件型別


3.過載運算子:利用現有的運算子,針對自定義的類或者結構定義某種運算操作,(不能是自己創造的運算子,不能是預定義的型別如int String等)。過載運算子可以簡化自定義型別的操作,更加方便和直觀。
  當運算子是一元運算子的時候 運算元必須是類或者結構中的一種,如果運算子是二元的時候,兩個運算元中必須有一個是類或結構


public static Pet operator ++(Pet pet){
++Pet.age;
}
 pet++; 此時pet物件因為過載了++運算子,所以,進行pet++的時候,是讓pet的age進行了+1
 pet.showAge();


泛型,約束:
通過約束,更好的利用泛型,泛型引數可以有多個即T1 T2 T3 
同時約束就是利用where語句對特定的泛型進行約束,
void  home<T> where T: (1.主約束 2.介面約束 3.構造約束)
主約束只能有一個可以是某個具體的類名,class,結構, 介面約束可以有任意個
當具體到某個類名的時候,傳入的只能是這個類的型別的物件,class則表示必須傳入一個類型別物件,即不能是int之類的值型別。當確定了傳入的類之後,就可以直接呼叫傳入的這個主約束中的方法,介面也是同理,當傳入構造約束以後。就可以在泛型方法中建立例項物件了。




集合:
Arraylist是動態陣列,什麼都能放,是一維的,但是也是型別不安全的,所以有了List<T>泛型,但是這裡就會存在裝箱和拆箱的操作,效能上有損失兩者都有add remove,count等方法,可以通過索引來訪問和刪除指定索引位置的資料


Dictionary字典,類似於java中的Map。它的數量也是count方法,新增的時候需要新增兩個,一個是key一個是value。訪問則直接通過key來進行訪問,更加的方便管理,但是


stack棧是先進後出,類似只有一個開口的容器,
pop出棧,push入棧,peek獲取棧頂元素


queue隊是先進先出,類似於水管,兩頭都開口的容器。
dequeue 出隊, enqueue入隊


委託:
委託就是持有一個或者多個方法的物件!並且該物件可以執行可以傳遞,使用delegate宣告
可以將物件的方法賦給委託物件
delegate void A();
 A del=dog.speak;
 del+=dog.run;


使用方式:與使用函式一樣直接使用委託名加括號的方式del(); 
  委託可以持有多個方法,呼叫一次,
就可以把委託中的方法全部執行一遍


Lambda表示式:即匿名的委託
del=()=>{}
del+=()=>{
方法具體.....
}


事件:可以理解為是一種封裝的,受限制的委託
1訂閱:關注某個事件發生
2釋出:通知某個事件發生
3註冊:想要在事件發生時被通知,必須要註冊
觸發,即當事件發生時,呼叫訂閱者的註冊函式,註冊就是告訴釋出者應當呼叫哪個註冊函式


事件的訂閱 newdog += 方法  表示關注  newdog -= 方法 表示取消關注,方法可以是實力方法,靜態方法,匿名方法,Lambda表示式
其中的newdog就是事件名,即想要關注的是哪個事件


事件觸發 if(newdog!=null){
          newdog();
  }
對事件進行判斷,如果不為空,則代表有關注者,也就是被訂閱了,那麼就執行這個委託事件


public delegate void handler(); //定義一個委託型別
public static event handler newdog;       //定義一個委託事件


在需要進行事件觸發的地方進行事件的判斷,與觸發


同時進行事件的訂閱,也就是註冊 dog.newdog += 方法