19.平台語言
見其可欲也,則必前後慮其可惡也者;見其可利也,則必前後慮其可害也者 ——《荀子·不苟》
逗號提出:“現在應該到了Java時間吧。”
冒號順水推舟:“下面談論的重心從剛才的系統語言轉到平台語言——Java和C#。”
問號聽得一頭霧水:“平台語言?Java不是平台無關的語言嗎?”
“平台的意義很廣,可以是硬件平台,可以是軟件平台,也可以是二者的結合。”冒號解釋道,“你說的‘平台’主要指硬件和操作系統平台,而我說的‘平台’指的是運行環境平台。當然這兩種平台是密不可分的,Java與C#之所以能獨立於前一種平台,正因為它們自帶了後一種平台。具體地說,Java運行於以Java Virtual Machine (JVM) 為核心的Java平台,而C#運行於以Common Language Runtime (CLR)為核心的.NET平台。”
句號打了個比方:“這就好比在不同的山路上鋪設相同的瀝青,車子跑到哪兒都沒區別了。”
“很形象。”冒號贊道,“從傳承的角度看,二者皆為基於C++之上的改進,剔除了其中易於出錯或不易掌握的語法特征。我們先來看看它們區別於C++的共同之處。首先,二者均編譯成與機器無關的托管碼(managed code)或稱字節碼(bytecode),運行於虛擬機(virtual machine)之上。其次,禁用或限用指針並支持自動垃圾回收,由此極大地解放了程序員的生產力。起初這種做法並不是沒有爭議的,但隨著機器性能的提高以及軟件規模的擴大,對軟件的健壯性、安全性和生產率的要求超過了對運行效率的要求,屏蔽指針和自動內存管理逐漸得到認同。盡管如此,指針與手動內存管理對於系統軟件和實時性要求極高的軟件還是必不可少的。一個佐證是,Java 除了不適用於系統軟件外,還在JDK免責聲明(disclaimer)中表示它是不適用於空中交通或核設施等實時系統的。”
引號較起真來:“那C#沒有這種聲明是否意味著它不受此限呢?”
“或許吧。”冒號淡淡地說,“C#的胃口很大,上管天、下管地、中間還要管空氣。企業級應用和桌面應用自不必說,底層應用也不放過。早在2003年,微軟研究院就開始了用C#開發的名為Singularity的操作系統研究項目,另外還有SharpOS、Cosmos等開源操作系統。雖然它們目前僅用於研究,但不難看出C#的勃勃野心。說起來這也不新鮮,1998年Sun就搞了個針對嵌入式系統的JavaOS,可惜沒能成功,為Java ME所取代。”
輪到歎號糊塗了:“剛才還說Java和C#是平台語言,怎麼又同C和C++一樣當系統語言來用了呢?”
冒號釋疑:“Java可通過JNI調用C、C++等程序;C#可通過P/Invoke訪問系統API,加之保留了指針操作,用於系統編程更加方便。其實一種語言勝任多種領域並不難,難的是在每個領域都獨占鳌頭。可問題是,有誰不樂見自己支持的語言被廣泛應用呢?無論是微軟還是Sun,他們都會竭盡所能地將自己的語言擴張到每個角落。程序員作為語言的用戶,雖然很多時候並沒有選擇語言的權力,但心中要有桿秤,可不要輕易被商家的廣告迷惑啊。”
逗號不無自嘲地說:“秤倒是有一桿,就是不太准啊!”
有人“噗哧”笑出聲來。
“多學習、多實踐、多體悟,秤的精度自然會提高。”冒號鼓勵道,“如果自己沒有足夠的鑒別商品能力,建議從商家的競爭對手那裡獲取真實的信息。要看Java的優點,不要聽Sun的一面之詞,可以看看微軟的C#模仿了Java的哪些特征,因為模仿是最高的贊揚;要看Java的缺點,可以看看C#擯棄了Java的哪些特征,可以聽聽微軟對Java的批判——雖然可能過激,但一般也不會太離譜。此法同樣適用於包括C#在內的其他語言。”
句號有所感慨:“這既是程序員之幸——語言之間可以互相取長補短,共同進步;也是程序員之不幸——往往不得不在眾多語言中作艱難選擇,或者多花精力學更多的語言。”
冒號一邊點頭一邊接著說:“下面繼續看看Java與C#的共性。借著剛才的話題,我們來看看C#與Java是如何互相學習的。”
引號舉手插問:“C#到底更接近C++還是Java?”
“這是個有趣的問題。不妨這麼說:C#看起來像C++,用起來像Java。C#借鑒了包括Java、C++、Delphi等在內的語言特征,其中Java的影響最大,但由於微軟與Sun在Visual J++上的過節,寧願強調與C++的關系而淡化與Java的關系。C#的設計者Hejlsberg以前是Delphi和Visual J++的架構師,在一次訪談中首先聲明C#不是Java的克隆,但從此話本身和他本人的背景都暗示了與Java千絲萬縷的聯系。例如,C#采用了大量與Java相同或相似功用卻不同拼寫的關鍵詞。”冒號投影出一張表格——
Java super import package synchronized instanceof deprecated final native boolean C# base using namespace lock is obsolete sealed extern bool“這只是Java與C#關鍵詞的不完全對照表。中立地看,C#的關鍵詞更簡明,但避嫌的意義似乎大過改進的意義。那麼C#究竟從Java那裡學到了什麼,相比於C++又有什麼優勢呢?”冒號切換了幻燈片——
更加安全——限用或禁用指針;檢查字符串和數組的邊界;增加類型安全;禁用未初始化的變量;增加了對資源的安全管理;
更加簡單——自動垃圾回收;廢除了頭文件和宏(macro);支持接口(interface);廢除多繼承以及非公開繼承;摒棄了C++中一些生僻、難用的語法;
更加OO——不支持全局變量和自由函數;所有的類都可上溯到Object類;對象一般通過new分配在堆(heap)上;
更加豐富——支持自省(Reflection);支持線程;提供圖形界面、網絡編程等API;
更加標准——對Unicode的內建支持;支持注釋性文檔;類或方法可以被廢棄(deprecated);
更加中性——編譯成機器無關代碼;運行於統一平台;
問號順勢而問:“Java向C#又借鑒了什麼呢?”
冒號答道:“在Java1.5的增強特征中,有不少C#的影子。如增強版的for循環;可變長參數(varargs);自動裝箱(autoboxing);類型安全的枚舉(typesafe enum)等等。此外,支持元數據的的注釋(annotation)與C#的特性(attribute)大同小異,C#從Delphi中引入的屬性(property)也出現在Java 7的提案中。”
歎號雙手一攤:“這麼多相同之處,不如合並算了。”
“很傻很天真的想法。等它們合並了,估計世界也大同了。”冒號笑言,“它們之間的差別也不容忽視。C#重新撿起了C++中被Java拋棄的一些特征,可謂是對C++的否定之否定——除了支持引用類型(reference type)外,還支持值類型(value type);除了按值傳遞(pass-by-value)外,還可按引用傳遞(pass-by-reference);支持操作符重載(operator overloading);在一定條件下保留指針和指針運算;所有的方法默認是非虛的(non-virtual);訪問權限默認是私有的(private);將關鍵詞‘extends’和‘implements’統一為‘:’;支持預處理指令(preprocessor directive)等等。公允地說,這些大都為明智之舉。”
引號追問:“C#還有什麼獨到之處嗎?”
“曾在Visual J++中加入的委托(delegate)和相關的事件(event),如今可以堂而皇之地用在C#上,再不用擔心被Sun告了。”冒號略帶調侃,“C#還是第一個支持組件導向(Component-Oriented)的C族語言。除此之外,C#支持索引器(indexer)、版本控制(versioning)、XML注釋、特色指令如#region、特色關鍵詞如checked、yield等等。”
歎號眉頭微蹙:“聽起來C# 比Java復雜多了。”
“當初Java對C++的改革的一個重要原則是:讓語言變得簡單而有親和力,降低程序員門檻,提高軟件生產效率。但如今Java已經不那麼簡單了,C#則更復雜,在某些方面較之C++也不遑多讓。”冒號語調轉強,“以前人們試圖在語言的威力(power)和生產率(productivity)中尋求最佳平衡點,現在似乎更想魚與熊掌兼得。”
問號提問:“Java與C# 最大的區別是什麼?”
“雖然同為平台語言,二者的設計理念還是有所不同的。Java的目的是讓一種語言在多種平台上運行,而C# 的目的是讓多種語言在一種平台上運行。”冒號鐘愛這種具有對稱美的對比,“雖然理論上以C#為核心的.NET平台可以用在任何操作系統上,但千萬不要指望微軟會心甘情願地提供Windows之外的實現,原因不言自明。而Sun的Solaris無法與Windows抗衡,最大的王牌就是Java語言,當然會致力於跨平台和面向Internet的應用,對桌面應用的投入相對較少。因此兩個平台語言,一個重在語言,讓語言向平台擴散;一個重在平台,讓平台來凝聚語言。在此並不想對兩公司的商業策略評頭論足,而是認為了解這種背景會對理解語言特征及其發展趨勢有所裨益。編程語言絕非象牙塔中之物,實乃技術和商業合力推動的結果。”
逗號拖著怪腔:“原來如彼!”
眾人大笑。
句號深思後問道:“可不可以這麼理解:如果開發僅限於Windows平台的應用,C#是更好的選擇,它一方面與Windows系統存在天然的紐帶,另一方面可有效地利用.NET的包括ASP.NET、VB.NET、ADO.NET、WinForms等在內的各種軟件資源;如果開發不限於Windows的企業應用,則選擇Java更合適?”
“有一定道理,平台的確是語言選擇的一個考慮因素。不過說起可利用的軟件資源,Java毫不遜色。除了形形色色的框架外,與動態語言如Groovy、Scala、Ruby、Python等也能嚴絲合縫。”冒號匆匆結語,“關於Java與C#的比較暫時談到這裡,由於時間關系,我們不可能面面俱到,難免掛一漏萬。許多概念術語只是點到為止,具體細節留待以後展開,暫且按下不表。每種語言都為解決問題提供了一定的途經:C++提供了一馬平川的大路,也提供了陷阱密布的小道;Java則在大路上鋪設水泥,同時封鎖了捷徑小道;C#同樣填平了大路上的坑坑窪窪,但把一些小道上‘此路不通’的牌子偷偷改成了‘此路危險’。”