今天我以一個(gè) Ruby 吹的身份竟然被一個(gè) Java 吹罵了一通,大為震驚。遙想當年,我在開(kāi)源哥 Lisp 吹的攻勢下一直堅守著(zhù) Java 吹的可惡嘴臉的時(shí)候也不至于這么胡來(lái)。Java 是一門(mén)簡(jiǎn)單易學(xué)的語(yǔ)言,然而要想深入理解 Java 確實(shí)一件不簡(jiǎn)單的事。某些銷(xiāo)售自以為精通 Java,竟在我面前一派胡言,簡(jiǎn)直是有辱 Java 吹的資格。吹 Java 自然能吹的地方很多,但吹錯地方可就是吹錯了牛皮,所謂一粉頂十黑。不但吹得毫無(wú)力量,反而會(huì )被別人恥笑。本已無(wú)心撕逼,誰(shuí)知對方竟然還認真了起來(lái),質(zhì)問(wèn)起我懂不懂 Java 的反射機制。打開(kāi)電腦的我差點(diǎn)沒(méi)把早飯給笑出來(lái),如此狂妄之人恐怕我見(jiàn)得還不多。對方還擺出一副老司機的嘴臉,和稀泥一般地說(shuō)道:沒(méi)有最好的語(yǔ)言,只有最好的程序員??此坪苡械览?,實(shí)則漏洞百出。其實(shí)從來(lái)就沒(méi)有最好的語(yǔ)言和最好的程序員,問(wèn)題是項目的需求適合怎么樣的語(yǔ)言和程序員來(lái)開(kāi)發(fā)。但要想挑起圣戰,自然要先站隊。那么我作為一名多年的 Java 吹的身份今天我來(lái)教教你,Java 應該怎么吹??紤]到篇幅有限,今天就算答個(gè) 60 分的版本,剩下 40 分留給你自己參悟吧。
首先我們先要糾正一些已有的、常見(jiàn)的錯誤觀(guān)點(diǎn)。比如這位銷(xiāo)售吹起 Java 時(shí),給出了四大理由:1. Java 擁有強大的庫支持。2. Java 語(yǔ)言為了互聯(lián)網(wǎng)開(kāi)發(fā)的需求而設計。3. Java 可以直接在 Linux 上運行。4. Java 的內核小。恭喜你,以上四點(diǎn)基本上是 Oracle 的銷(xiāo)售才說(shuō)得出的話(huà)。你沒(méi)有看穿,實(shí)在是你悟性不夠。
JRE 自帶的庫確實(shí)是主流語(yǔ)言中最豐富的,但要想說(shuō)強大還得要 Maven 或者 Gradle 的支持。Java 之所以要包含這樣豐富的庫,其理由是非常單薄的。因為在解決一個(gè)問(wèn)題的角度上來(lái)說(shuō),Java 不存在許多實(shí)現。Java 的最佳實(shí)現是利用 Java 的庫實(shí)現。其目的是為了讓程序員拋開(kāi)底層,將目光集中在解決問(wèn)題上。同時(shí),這利于程序員數量規模巨大的團隊,代碼的交付成本可以有效降低。而底層怎么做,由 Java 的運行環(huán)境自身來(lái)決定。這一點(diǎn)有好有壞,最大的弊端就是,需求的本質(zhì)是多變的。Java 的庫不能很好給出最佳的庫實(shí)現。通常需要引入第三方庫才能更好開(kāi)發(fā)。然而 Java 引入第三方庫的形式通常是愚蠢的,直到 Gradle 和 Maven 的到來(lái)才解決了部分問(wèn)題。
Java 語(yǔ)言是為了互聯(lián)網(wǎng)設計的嗎?這句話(huà)顯然是錯的。Java 的野性顯然是占領(lǐng)一切平臺,從客戶(hù)端、服務(wù)器到移動(dòng)設備甚至超級計算機無(wú)所不涉及。為了做到這一點(diǎn) Java 引入了一個(gè)非常關(guān)鍵的技術(shù),我們通常稱(chēng)之為 JVM(Java Virtual Machine),通過(guò)一個(gè)虛擬技術(shù),來(lái)實(shí)現各個(gè)平臺的兼容。這項技術(shù)看起來(lái)非常完美,實(shí)則不然。Java 的代碼從一開(kāi)始就不是什么「一次編譯,到處運行」的,而是「一次編譯,到處調試」的,這一點(diǎn)當年用 Java 給 Nokia 各種手機開(kāi)發(fā)的程序員一定深有感觸。直到近年,這樣的麻煩才得到了一定程度的改善。更糟糕的是,各個(gè)平臺對于性能的需求側重點(diǎn)是有很大不同的,這就直接導致 Java 的性能存在問(wèn)題。當年 Google Android 團隊費盡心思寫(xiě)了比 JVM 更快的 Dalvik 虛擬機才敢把 Java 往 Android 上推,然而卡頓的問(wèn)題依然很?chē)乐?。直?Android 5.0 引入了 ART 虛擬機才大大改善。為什么能改善呢?因為運行在 JVM 上的 Java 代碼并不是機器碼而是 Byte Code,雖然引入了 JIT 技術(shù)進(jìn)行優(yōu)化,但是對于交互的延遲一直是存在的問(wèn)題。性能上不能適應即時(shí)的操作響應意味著(zhù)很難用于客戶(hù)端;閉源的 JVM 使得超算也不能獨立對其優(yōu)化;強制打開(kāi)的 GC 使得對延遲有要求的程序更是望而卻步。拋開(kāi) Google Android 團隊單獨對其優(yōu)化的 ART 虛擬機的話(huà)(Google 還因此被起訴了)。這使得 Java 只剩下一條路可走,那就是互聯(lián)網(wǎng)服務(wù)器。Java 并不為互聯(lián)網(wǎng)所設計,不過(guò)是只剩這一條路可走而已。服務(wù)器的主要功能不過(guò)封裝在一個(gè)叫 Servlet 的類(lèi)下而已,Servlet 甚至不是一個(gè)完整的程序。更糟糕的是,很少有人直接用 Servlet,而是要用更高的封裝的框架來(lái)使用。就這么來(lái)看,Java 怎么可能是為了互聯(lián)網(wǎng)設計的呢?這句話(huà)自古以來(lái)就是 Oracle 公司斂財的時(shí)候才開(kāi)口敢講的話(huà)。
至于 Java 可以直接在 Linux 上運行就更貽笑大方了。語(yǔ)言自古以來(lái)和操作系統毫無(wú)關(guān)系。Ada/C/C++/Python/Ruby...都能跨平臺運行。就算是萬(wàn)惡資本主義家的微軟,也有 Xamarin 實(shí)現了 Linux 上的 C# 和 VB.net。相比之下,Java 的兼容性并不是最好的。再加上 Oracle 商業(yè)化的嘴臉,使得第三方的編譯器并不多,實(shí)在是怕起訴。從這點(diǎn)看,根本沒(méi)有什么值得炫耀的。
另外說(shuō),Java 內核小的。。。大概。。。你需要先學(xué)習一下,內核是什么再說(shuō)這句話(huà)吧。
要想吹好 Java 首先要知己知彼。這一點(diǎn)也就是所謂多說(shuō)自己的優(yōu)勢,直戳別人的弱點(diǎn)。拿著(zhù)自己的弱點(diǎn)還以為自己很高級的,那就實(shí)在太傻比了。想吹好 Java 我們可以從三個(gè)角度入手。商業(yè)基因、虛擬環(huán)境和語(yǔ)言設計三個(gè)角度來(lái)談。
要知道 Java 是一家商業(yè)公司運營(yíng)著(zhù)的語(yǔ)言。這意味著(zhù)在商業(yè)上 Java 擁有著(zhù)更好的優(yōu)勢。這其實(shí)是大公司使用 Java 的一大誘因。商業(yè)公司的本質(zhì)是利益驅動(dòng)的。這就是為什么 Java 在各大路徑都走失敗后堅持要走互聯(lián)網(wǎng)的路。服務(wù)器的支出是 Oracle 賺錢(qián)的大頭。Oracle 可以連帶著(zhù)硬件一起把解決方案賣(mài)給你,這使得你有任何問(wèn)題都可以一個(gè)電話(huà)聯(lián)系到技術(shù)人員為你維護。而不像開(kāi)源程序出了 bug 都不知道找誰(shuí)更好。這樣的基因決定了很多事情,比如為了更好地推廣 Java,Oracle 有意扶植更多機構培訓 Java。這使得無(wú)論是國內還是國外都有大量 Java 程序員。雖然大多數 Java 程序員水平都很糟糕,并不能理解 Java 的深刻內涵。但是由于 Java 中最佳實(shí)現就是庫實(shí)現,而對于庫實(shí)現,Oracle 通常提供詳盡的文檔以供查詢(xún)。這使得很差的程序員也能負責一定的代碼。寫(xiě)出數量驚人的程序。代碼在移交的時(shí)候相比其他語(yǔ)言難度小很多,使得人員流動(dòng)頻繁也不至于對開(kāi)發(fā)進(jìn)度造成致命的影響。編程是一項和人息息相關(guān)的工作,如果無(wú)法解決人員流動(dòng)帶來(lái)的影響,對于大公司來(lái)說(shuō)存在太大的風(fēng)險??v使 Java 的開(kāi)發(fā)周期不短、代碼行數很長(cháng)、運行效率一般,但比起人員上的解決難度,可以說(shuō)都不是問(wèn)題。這一點(diǎn)為開(kāi)發(fā)帶來(lái)了得天獨厚的條件,是除了 C# 以外其他語(yǔ)言都不具備的優(yōu)勢。
當然,商業(yè)上的原因是一部分,但 Java 產(chǎn)品本身也并不差。一個(gè)很大的優(yōu)勢是 Oracle 自家開(kāi)發(fā)的 JVM。JVM 對于動(dòng)態(tài)特性的良好支持以及采用了棧作為主要的存儲結構是很好的選擇。它大大優(yōu)化了理解 JVM 的難度。而 Oracle 公司對其不斷的新特性的補充,使得 JVM 在中間層的虛擬機上是一個(gè)很不錯的選擇。無(wú)論是 Python、Ruby,甚至是一些基于 lambda 演算的語(yǔ)言比如 Clojure、Scala,都能在 JVM 上運行并獲得不錯的性能。而 JVM 增加的特性通常也是為下一版本 Java 語(yǔ)言的修訂進(jìn)行試水。比如是否提供更方便的泛型支持等問(wèn)題在 JVM 升級后的一些討論后能給出更有說(shuō)服力的結果。作為一門(mén)商業(yè)味道濃的語(yǔ)言,一步一個(gè)腳印的升級更能打動(dòng)別人。而隨便增加新特性,有時(shí)確實(shí)令人很反感。
Java 語(yǔ)言設計上的優(yōu)勢其實(shí)是最小的。論反射機制,你效率再高,和 Lisp 的各種花式閉包比起來(lái),實(shí)在是可笑不自量,即使是 Scala 的 Cake Pattern 也完全不能與之一戰。Java 語(yǔ)言設計上最大的優(yōu)勢其實(shí)不是特性,而是限制。比如類(lèi)的繼承的限制、比如只能使用不可移動(dòng)的引用、比如不能直接操作內存、比如不能濫用閉包。這些限制大大降低了程序員「玩壞」代碼的可能性,使得代碼易寫(xiě)、易讀、易維護。從「人月神話(huà)」的角度來(lái)看,一個(gè)技術(shù)團隊不宜人數太多,而 Java 提供了一種人數多時(shí),開(kāi)發(fā)不會(huì )太受影響的解決方案,更重要的是,公司就算程序員跑路,也不至于受到太大的影響,更何況比起小眾的語(yǔ)言,Java 程序員非常容易招聘,也更有保障。使用 Java 就好像買(mǎi)了一份保險,看起來(lái)保費巨大,但想想后果,其實(shí)還是值得權衡利弊的。
就這三點(diǎn)來(lái)說(shuō),其實(shí)能與之一戰的只有 C#,然并卵。因為 C# 不過(guò)是 Java 的另一種實(shí)現而已。
這樣才叫 Java 吹,某些人看了兩天教材再被人一鼓吹說(shuō)出口的那種圖樣圖森破的吹那個(gè)不叫吹,叫黑。
聯(lián)系客服