2008年1月28日

Java與c#,誰好誰壞?

今天被同學問了這樣一個問題,「假如有個程式語言的新手想學物件導向的語言,Java和c#選哪個比較好?」又問「Java好,好在哪?」

我基本上算是學Java的人,在7~8年前時,當時玩DNS、防火牆、NAT、Apache...等網路的東西,可是漸漸發現一個問題,我沒有寫程式的能力,沒辦法根據自己需要來寫工具,因此我當時希望學習一套程式語言來作為寫工具的武器。
當時正好是php/Flash/Java熱門的時候,在用php和Flash開發時,發現php3+Flash4有不足的地方,加上前面希望學套程式語言的理由,我在C和Java間抉擇,最後很自然的選了Java。
原因有幾個:
1.Java可以寫Java Applet,補足php+Flash的不足(現在Flash本身就強到爆了...)
2.我當時已經用FreeBSD一段時間了(2,3年了),我希望能在FreeBSD/Linux/Windows下都能寫程式
3.當時Java比較熱門,且號稱完全物件導向,和VB根本不能比
4.Java的特色中說,它的門檻介於VB和C之間,比較容易入門

因為這幾個原因,我開始學習Java,到現在雖然Java沒學很熟,寫的還是破破爛爛的,但總歸是我目前比較熟悉的語言。

c#是近年M$推的很大力的程式語言,它在Java後很多年推出,它許多特色跟Java相同,而且積極的要吸收Java的程式設計師,同時又「強烈建議」VB的程式設計師轉用c#。
目前看起來成果相當不錯,憑藉著M$高人一等的行銷和規劃,c#的確有相當大的一塊市場。

回到問題,那到底Java和c#要選誰來學呢?
我的回答會是,看你有沒有用Linux/FreeBSD/Sun...等Unix的需要,如果有,學Java比較好,因為Java可以跨大部分主流的PC平台作業系統。
如果你只會用Windows,也只會在Windows上開發程式,你根本沒碰過Linux,或者裝過一次之後發現那東西根本難用的像垃圾,那麼...學c#吧~
和c#相比,Java其實有許多缺點:
1.Java的效能真的比較差,和c#相比感覺還好,但如果和C/C++...等相比,它效能真的比較差
這沒什麼好說的,經過VM執行的程式效率就是會比較差,c#也有VM,所以兩者差異比較小,但c#有平台優勢,因此整體來說,我相信c#效率會比較好,至於C/C++,根本沒VM,又都是編譯式語言,根本不用比了

2.Java沒有很強大的瀏覽器元件
Java上的瀏覽器元件,怎麼看就只有Swing Editor,找到翻天也找不到好用的瀏覽器元件,只有一個例外,那就是SWT的Mozilla元件,但Java本身附的是Swing,換到SWT,光要找SWT的安裝就找半天(dll+jar的設定),整個SWT語法和Swing完全不同,要重學,如果只因為瀏覽器元件要用SWT,在Swing和SWT混合使用的情況時,會有輕量化物件和重量級物件互相干擾的問題,而且不好解決。
而這在c#上,你可以自由自在的使用IE的元件,儘管它漏洞多、容易中毒、效能差,但不可否認的是,他在目前有全世界最好網頁相容性(被M$壟斷的結果)和最好的支援性(ActiveX)。

3.Java沒有很強大的媒體播放元件
Java上的媒體播放元件,以Sun提供的來說,就是JMF(Java Media Framework),這東西用過的都知道,它是個垃圾。本身設計複雜、難用不說,一堆功能統通都沒有,得要自己寫,更殘忍的是,它基本上只支援極少數的影音編碼(Codec),常見的xvid、DivX、MPEG4、H.264...等格式,統統都不支援。
而這在c#上,你可以使用Media Player SDK,呼叫了Media Player SDK之後,就跟常見的MPC(Media Player Classic)一樣,你可以透過安裝各種編碼包(Codec Package)來支援各種影音格式。

4.Java的IDE並不好用
Java上幾套主流的IDE,像是NetBeans、JBuilder、Eclipse,基本上沒有Visual Studio好用,Visual Studio所見即所得的設計非常好,Eclipse本身沒有辦法拖拉元件來設計GUI,需要另外裝外掛,但是這類外掛多半要錢,免費的不很好用(我記得我是用JVisual...不知道有沒有記錯)。NetBeans是我覺得GUI比較好用的,但是它跑起來很慢,吃得記憶體又大。
JBuilder我完全不會用..... = =||

5.Java的第三方物件庫比較少,尤其是跟比較硬體的呼叫,根本沒有
Java的物件庫比較少,尤其是和C/C++相比,少了很多,和硬體有關的幾乎沒有,舉個簡單的例子,我如果希望寫個程式,這程式可以退出光碟機托盤,這就不容易辦不到了。再提個例子,我希望取得系統中檔案的Owner、權限,這也不大容易辦到。
而在c#,因為沒有跨平台的壓力,c#可以呼叫比較硬體的功能,儘管它不建議,但是是可以的。
但在Java上,受限跨平台的因素,因此這對Java來說,就不容易了。

這樣看起來,Java根本一無是處阿~總有優點吧!?
Java最大的優點有2個,跨平台和物件導向。
先說物件導向吧~
我一直不了解物件導向到底好用在哪裡,直到我學弟跟我說了之後,我才了解~
物件導向的程式語言有個特色,它的程式碼會比較容易看懂,因為不管怎麼變,它都是按照物件導向的概念在寫的,所以只要抓到繼承關係,要看懂程式碼是比較容易的。
Java的物件導向其實比較傳統,傳統的同義字差不多可以說是沒什麼彈性,我同學在學c#的物件導向,聽它敘述之後才知道,c#有很多Java沒有的物件用法,方便是滿方便的,可是不可否認,整個程式碼會變得比較複雜難懂些。
所以相比起來,我認為Java的物件導向是比較好的,畢竟有彈性未必是好事,一方面不一定會去用,用了之後,看得人就很辛苦了。

另一個Java的優勢是跨平台,也許會說,這有什麼大不了的,前面這麼多缺點,一個優點也想打平所有缺點嗎?
結果似乎真的是這樣~
一個只會寫Windows程式,只會用Visual Studio的人,很難了解「跨平台」這件事情的難度,我曾經聽過個事情,在3~4年前,Linux正好開始熱起來,我朋友告訴我一個有趣的事,它公司一個新來的程式設計師被老闆要求把公司的程式移植到Linux上跑,公司的程式是用VB(還是VC...忘了)寫的,那位可憐的新人如果能做到這樣的事情,它就不會到那家公司去了,它可以去告好的公司工作了..... = =||
一般當進一步被問到跨平台的差異時,討論區的高手往往都會說一句「作業系統架構不同」來打死所有人的回答,也打死了問的人,但是什麼叫做「作業系統架構不同」,這很難嗎?
因為最近剛好在學GNU C + GTK,多少能夠有些體會~

首先,Windows和UNIX的發展是平行的,經過了n年之後,它們已經發展出各自的架構出來了,整個系統堆疊出的方塊圖就完全不同,細部更是差異很大。
我們先從小的說起,在UNIX當中,所有Device都被當成一個檔案,然後全部放在/dev目錄下,要呼叫很簡單,直接按照檔案存取的方式來操作Device File,Device就會動了,那像印表機、掃描器之類的,直接read或write之後仍然不會動,是因為中間加入了protocol(通訊協定),因此需要按照通訊協定的方式來read和write。
在Windows裡面,你什麼時候看到過Device File?M$的作法是,針對特定裝置,提供特定的API讓你呼叫使用,你幾乎不需要知道protocol和Device的操作,反正呼叫之後,Windows作業系統就呼叫相對應的元件,頂多跳出系統的視窗來詢問你。
再來,Windows從很久以前就很愛用Registry,一些用電腦多年的人都知道,這裡面藏污納垢,反正系統設定檔、程式設定檔,統統不需要檔案,往裡面丟就對了,容易丟、容易取。
但在UNIX下,基本上沒有這樣的東西,近年GNOME有仿照這樣的形式來設計,但目前用的還沒有很誇張,通常只用在GUI環境,非GUI環境仍舊不用,也多半還是用很醜的設定檔來設定。
光小地方就有這麼大的差異,大地方呢?
Linux、FreeBSD、Sun...等系統,雖然都是UNIX like的系統,但是他們之間仍舊存在差異性,它們的process(程序)設計並不完全一樣,這點到了MacOS上也是,而到了Windows上差異更大,Windows沒有process,只有thread,而全部的系統,在使用process或thread時,呼叫的function不完全一樣,操作方法也不完全一樣。
這種,就是所謂的「作業系統架構不同」,要在不同的作業系統上開發程式,如果要寫到多執行緒,需要參考各作業系統相關的寫法,然後根據不同系統來寫。
再者,Linux...等UNIX like的作業系統,它們用的視窗系統通常是X-win,X-win下面又有視窗管理員(Window Manager)的設計,常聽到的GNOME、KDE就都是Linux下的視窗管理員(Window Manager),各視窗管理員間的API不一樣,因此同樣是寫視窗程式,在UNIX上可能很多套、很多種選擇、寫法。
到了Windows,整個架構又變了,呼叫的API也完全不一樣,寫法、操作差異性更大。

就是因為有這麼大、這麼多的差異性在,因此「跨平台」這三個字才會這麼巨大,讓它的重要性可以補足前面的缺點,事實上前面許多的缺點,根本問題正是「跨平台」所造成的。
這也是為什麼高手跳出來說一句「作業系統架構完全不同」,所有人就得乖乖閉嘴,因為這句話,就是在描述上面寫的一堆東西。
所以Java的神奇在於,它今天利用VM,在所有平台上建構出了相同的執行環境,讓Java程式執行,但問題就在於,VM沒辦法包山包海,比較依賴硬體或作業系統的功能,它做不到,也因為Java程式要透過VM執行,所以執行效率再快,也快不過C/C++這類機器碼的執行效率。
如果感受不深刻的人,尤其長期在Visual Studio下工作的人,試著看看訪間Linux程式設計的書,看看在Linux上寫多執行緒、寫網路程式、寫GUI要怎麼寫?和Visual Studio上的差別有多大?
你就能夠感受到Java的偉大了~

3 則留言:

T55555 提到...

> 但問題就在於,VM沒辦法包山包海,
> 比較依賴硬體或作業系統的功能,它做不到,

Yes or No.
Because we can use JNI to allow java to call native (C/C++) code to do any hardware or OS level actions.

匿名 提到...

http://shootout.alioth.debian.org/

C#的執行時間是java的兩倍
java的速度是快C#很多的

Cody 提到...

感謝回覆,這網站的測試非常有趣且值得參考。

測試中不只有Java和c#,
還包含Python、Ruby和其他幾種我沒見過的語言,
測試結果看起來,Java的效能非常高,
相當有趣。