Java與C#開發上的一些差異與轉換方法

來源:互聯網
上載者:User

此文尚未寫完,有時間逐漸補全。

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方法(當然,不照規矩走也沒人攔著),可以不成對出現。

比如

      private String name;

        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);
        }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.