Java與C 開發上的一些差異與轉換方法
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
此文尚未寫完,有時間逐漸補全。Java和C#訪問修飾符的差異性與轉換:
在C#中,我們通常會使用到如下幾種訪問修飾符:
public 訪問不受限制。
protected 訪問僅限於包含類或從包含類派生的型別。
internal 訪問僅限於當前程式集。
protected internal 訪問僅限於當前程式集或從包含類派生的型別。
private 訪問僅限於包含型別。
而在Java裡,則僅有以下幾種可供調配:
public 同C#一致
protected 同C#一致
private 同C#一致
internal 在Java中無等價存在(在Java中,如果不為函式或類增加任何修飾符,則意味著僅限當前包中所有類訪問,同internal作用有近似處,但範圍沒有internal大。而在C#中,不用任何範圍修飾符時,預設的則是protected,不能在類外被訪問)
另外C#的Type,基本等價於Java的Class,小弟在LGame的C#版中也提供有一些轉化工具(此類工具都在名稱空間Org.Loon.Framework.Xna.Java下)。
Java和C#中this關鍵字的差異性與轉換:
Java同C#的this關鍵字基礎作用一致,都是引用當前類的當前例項,但細節使用處有些差異。
比如在Java中,我們想利用this呼叫一個已有的建構函式,使用樣式如下:
public test{
this(0,0);
}
public test(int x,int y){
}
而在C#裡,則需要如下的使用方式:
public test : this(0,0){
}
public test(int x,int y){
}
而從派生類中訪問基類的成員,也就是呼叫父類的方法,則有如下分別。
Java中
public test(){
super(0,0);
}
C#中
public test():base(0,0){
}
Java和C#陣列的差異性與轉換:
Java與C#陣列的差異,主要體現在多維陣列的定義方式上(一維毫無差異)。
比如我們在Java中定義一個3x3的二維陣列,需要如下設定。
int[][] test = new int[3][3];
讀取方式則為如下:
int v = test[0][0]
而同樣的設定,C#中則必須寫成
int[,] test = new int[3,3];
讀取方式就要順應格式,變成這樣(附帶一提,小弟在LGame的C#版裡提供有仿寫Java陣列的方式):
int v = test[0,0];
另外,C#陣列設定上比較嚴謹,沒有Java那麼隨意。
比如Java中構建如下樣式陣列,不會有任何問題:
String test[] = new String[3];
而在C#中則必須為如下樣式:
string[] test = new string[3];
假如將[]寫在變數名而非變數型別後,C#是不認的,連編譯都過不去。
Java和C#函式差異性與轉換:
在Java中使用函式,不宣告[不可重寫],就可以直接[重寫]。
在Java環境中,如果我們需要一個公有方法不能重寫,需要宣告這個函式為final(基本等價於C#的sealed修飾符,但sealed僅對類有效)。
假設A類有公有函式:
public void test(){}
則B類無需任何修飾,複寫一次該函式,重寫就會被完成。
public void test(){}
如果我們不希望A類中函式test被重置,則需要特別修飾test函式,比如下例:
public final void test(){}
而在C#函式中,特性與Java正好相反,不宣告函式[可以重寫],意味著對應一定[無法重寫]。
在C#中,假設也有A類,想要完成如Java般操作,則必須先作如下設定:
public virtual void test(){}
而後需要重寫的B類,再做如下修飾,才能完整重寫過程(在C#裡,假如我們需要一個公有方法可以重寫,則必須宣告為override。Java雖然有override的元資料註釋,但可有可無……)。
public override void test(){}
而C#中不希望test被重置,則無需任何設定,直接如下即可:
public void test(){}
另外,virtual修飾符不能與 static、abstract, private或者 override修飾符同時使用(否則VS直接編譯失敗,根本無法走到執行)。
Java和C#全域性常量差異性與轉換:
有時我們需要一個數值永遠固定為單一量,這是我們就需要一個全域性常量。
在C#中,這點延續了標準C語系的做法,直接使用const關鍵字即可(不需要static描述,有此關鍵字就是全域性使用),比如:
public const int type = 0;
這樣,我們直接使用類名.type的方式,就可以在任何場合訪問到這個常量值。
而在Java中使用,實現同樣效果則比較麻煩,因為Java雖然有const關鍵字,卻是保留值(只佔位,無實際功能),而需要由final與static關鍵字結合使用,方可達到近似效果。比如:
public final static int type = 0;
這樣,我們使用Java類名.type的方式,才可以在任何場合都訪問到這個常量值。
另外在C#中,也可以使用下列方式來達到目的:
public readonly static int type = 0 ;
其實從本質上講,上述C#表述才和Java的常量用法更貼近(const欄位是編譯時常量,而readonly欄位可用於執行時常量,意味著初始化時有一次動態賦值的機會)。
Java和C#繼承的差異性與轉換:
在名稱上,C#與Java相同,都是類為class(但獲得當前類的class時,卻不能如Java般getClass,而要GetType) , 介面為interface,抽象為abstract。
但Java繼承類需要修飾符【extends】,實現介面需要修飾符【implements】。
比如:
public class Test extends A implements B {
}
而C#僅需一個【:】搞定。
public class Test : A , B {
}
編譯時系統會分清那個是繼承,那個是介面或其他型別(struct啥的不能被繼承)。
另外,想要阻止某個類被派生時,Java中可以使用final關鍵字,C#中可以使用sealed關鍵詞來修飾目標類。
不過C#中也有一個不如Java的特性,讓小弟非常彆扭,那就是interface中不能存在常量(不能包含域(Field),且函式前也不能存在public關鍵字),導致將Java的某些程式碼移向C#只能微調。
Java和C#屬性的差異性與轉換:
在Java中定義和訪問屬性,在規範上要用get和set方法(當然,不照規矩走也沒人攔著),可以不成對出現。
比如
public void setName(string n){
this.name = n;
}
public string getName(){
return this.name;
}
而在C#中,則可以直接用如下方式來訪問name。
public string name
{
set;
get;
}
此外,Java中我們也可以直接將name設定為public的,這樣表面功能上同上述C#語法彷彿沒有區別。但是,在C#中我們卻可以自由限制該方法的set和get屬性,以調控究竟暴露給使用者怎樣的操作許可權,要比Java中批量生成海量Set與Get方便一些。
附帶一提,如果我們呼叫C#的Type中GetMethods方法遍歷函式,可以看見name將變成如下樣式。
set_name
get_name
其實C#就是替我們自動新增好了set與get屬性,與Java在執行機制上倒沒有本質區別。
Java和C#在多執行緒管理上的差異性與轉換:
C#中使用MethodImplOptions.Synchronized進行執行緒同步
[MethodImpl(MethodImplOptions.Synchronized)]
public void test(){
}
大體等於Java中
public synchronized void test(){
}
C#中使用lock關鍵字作為互斥鎖
object o = new object();
public void test(){
lock(o){
}
}
大體等於Java中
Object o = new Object();
public void test(){
synchronized(o){
}
}
C#中使用Monitor.Enter作為排他鎖
List<object> list = new List<object>();
public void test()
{
Monitor.Enter(list);
//具體的list排它操作
//......
Monitor.Exit(list);
}
在Java中沒有等價存在,不過有一些功能近似類在java.util.concurrent.locks包下可供調配,比如寫成這樣:
ReentrantReadWriteLock ilock = new ReentrantReadWriteLock();
Lock readLock = ilock.readLock();
Lock writeLock = ilock.writeLock();
List<Object> list = new ArrayList<Object>();
public void test() {
try {
// 讀取鎖定
readLock.lock();
// 寫入解鎖
writeLock.unlock();
// 具體的list排它操作
// ......
} finally {
// 讀取解鎖
readLock.unlock();
// 寫入鎖定
writeLock.lock();
}
}
其它C#多執行緒常用函式與Java間函式的關係,可參見如下實現(也可參考LGame的C#版JavaRuntime類中):
public static void Wait(object o)
{
Monitor.Wait(o);
}
public static void Wait(object o, long milis)
{
Monitor.Wait(o, (int)milis);
}
public static void Wait(object o, TimeSpan t)
{
Monitor.Wait(o, t);
}
public static void NotifyAll(object o)
{
Monitor.PulseAll(o);
}
public static void Notify(object o)
{
Monitor.Pulse(o);
}