原文鏈接:http://www.yinwang.org/blog-cn/2016/01/18/java/?from=timeline&isappinstalled=1
原文鏈接已失效畴博,本文從博客園搬過(guò)來(lái)蔬崩!
文/王垠
有些人問(wèn)我,在現(xiàn)有的語(yǔ)言里面弥臼,有什么好的推薦?我說(shuō):“Java∫人眨” 他們很驚訝:“什么?Java醇疼!” 所以我現(xiàn)在來(lái)解釋一下硕并。
Java 超越了所有咒罵它的“動(dòng)態(tài)語(yǔ)言”
也許是因?yàn)槟贻p人的逆反心理,人們都不把自己的入門(mén)語(yǔ)言當(dāng)回事秧荆。很早的時(shí)候倔毙,計(jì)算機(jī)系的學(xué)生用 Scheme 或者 Pascal 入門(mén),現(xiàn)在大部分學(xué)校用 Java乙濒。這也許就是為什么很多人恨 Java陕赃,瞧不起用 Java 的人。提到 Java,感覺(jué)就像是爺爺那輩人用的東西么库。他們說(shuō)傻丝,Java 老氣,龐大诉儒,復(fù)雜桑滩,臃腫。
某些 Python 程序員允睹,在論壇里跟初學(xué)者講解 Python 有什么好运准,其中一個(gè)原因竟然是:“因?yàn)?Python 不是 Java!” 他們喜歡這樣宣傳:“看 Python 多簡(jiǎn)單清晰啊缭受,都不需要寫(xiě)類(lèi)型……” 對(duì)于 Java 的無(wú)緣無(wú)故的恨胁澳,盲目的否認(rèn),導(dǎo)致了他們看不到 Java 很重要的優(yōu)點(diǎn)米者,以至于迷失自己的方向韭畸。雖然氣勢(shì)上占上風(fēng),然而其實(shí) Python 作為一個(gè)編程語(yǔ)言蔓搞,是完全無(wú)法和 Java 抗衡的胰丁。
在性能上,Python 比 Java 慢幾十倍喂分。由于缺乏靜態(tài)類(lèi)型等重要設(shè)施锦庸,Python 代碼有 bug 很不容易察覺(jué),察覺(jué)了也不容易 debug蒲祈,所以 Python 無(wú)法用于構(gòu)造大規(guī)模的甘萧,復(fù)雜的系統(tǒng)。你也許發(fā)現(xiàn)某些 startup 公司的主要代碼是 Python 寫(xiě)的梆掸,然而這些公司的軟件扬卷,質(zhì)量其實(shí)相當(dāng)?shù)牡汀T诔墒斓墓纠锼崆眨琍ython 最多只用來(lái)寫(xiě)工具性質(zhì)的東西怪得,或者小型的,不會(huì)影響系統(tǒng)可靠性的腳本卑硫。
靜態(tài)類(lèi)型的缺乏徒恋,也導(dǎo)致了 Python 不可能有很好的 IDE 支持,你不能完全可靠地重構(gòu)(refactor)Python 代碼拔恰。PyCharm 對(duì)于早期的 Python 編程環(huán)境因谎,是一個(gè)很大的改進(jìn)基括,然而理論決定了颜懊,它不可能完全可靠地達(dá)到“變量換名”等基本的 refactor 操作。
在設(shè)計(jì)上,Python河爹,Ruby 比起 Java匠璧,其實(shí)復(fù)雜很多。缺少了很多重要的特性咸这,有毛病的“強(qiáng)大特性”倒是多了一堆夷恍。由于盲目的推崇所謂“正宗的面向?qū)ο蟆狈绞剑^“l(fā)ate-binding”媳维,這些語(yǔ)言里面有太多可以“重載”語(yǔ)義的地方酿雪,不管什么都可以被重定義,這導(dǎo)致代碼具有很大的不確定性和復(fù)雜性侄刽。Python 和 Ruby 代碼很容易被濫用指黎,不容易理解,容易寫(xiě)得很亂州丹,容易出問(wèn)題醋安。
很多 JavaScript 程序員也盲目地鄙視 Java,而其實(shí) JavaScript 比 Python 和 Ruby 還要差墓毒。不但具有它們的所有缺點(diǎn)吓揪,而且缺乏很多必要的,方便的特性所计,比如基本的 class 定義都沒(méi)有柠辞。JavaScript 的各種“WEB 框架”,層出不窮主胧,似乎一直在推陳出新钾腺,而其實(shí)呢,全都是在黑暗里瞎蒙亂撞讥裤。JavaScript 的社區(qū)以幼稚著稱放棒。你經(jīng)常發(fā)現(xiàn)一些非常基本的常識(shí)己英,被 JavaScript“專家”們當(dāng)成了不起的發(fā)現(xiàn)似的间螟,在大會(huì)上宣講。我看不出來(lái) JavaScript 社區(qū)開(kāi)那些會(huì)議损肛,到底有什么意義厢破,仿佛只是為了拉關(guān)系找工作。
Python 湊合可以用在不重要的地方治拿,Ruby 是垃圾摩泪,JavaScript 是垃圾中的垃圾。原因很簡(jiǎn)單劫谅,因?yàn)?Ruby 和 JavaScript 的設(shè)計(jì)者见坑,其實(shí)都只是民科嚷掠。
Java 的“繼承人”沒(méi)能超越它
最近一段時(shí)間,很多人熱衷于 Scala荞驴,Clojure不皆,Go 等新興的語(yǔ)言,他們以為這些是比 Java 更現(xiàn)代熊楼,更先進(jìn)的語(yǔ)言霹娄,以為它們最終會(huì)取代 Java。然而這些狂熱分子們逐漸發(fā)現(xiàn)鲫骗,Scala犬耻,Clojure 和 Go 其實(shí)并沒(méi)有解決它們聲稱能解決的問(wèn)題,反而帶來(lái)了它們自己的毛病执泰。這些毛病很多是 Java 沒(méi)有的香追。
關(guān)于 Go,我已經(jīng)評(píng)論過(guò)很多了坦胶,有興趣的人可以看這里透典。總之顿苇,Go 是民科加自大狂的產(chǎn)物峭咒,這里我就不多說(shuō)它了。
我認(rèn)識(shí)一些人纪岁,開(kāi)頭很推崇 Scala凑队,仿佛什么救星似的。我建議他們別去折騰了幔翰,老老實(shí)實(shí)用 Java漩氨。沒(méi)聽(tīng)我的,結(jié)果到后來(lái)遗增,成天都在罵 Scala 的各種毛病叫惊。但是沒(méi)辦法啊,項(xiàng)目上了賊船做修,不得不繼續(xù)用下去霍狰。我不喜歡進(jìn)行人身攻擊,然而我發(fā)現(xiàn)一個(gè)語(yǔ)言的好壞饰及,往往取決于它的設(shè)計(jì)者的水平蔗坯,人品,和動(dòng)機(jī)燎含。很多時(shí)候我看人的直覺(jué)是異常的準(zhǔn)宾濒,以至于依據(jù)對(duì)語(yǔ)言設(shè)計(jì)者的第一印象,我就能預(yù)測(cè)到這個(gè)語(yǔ)言將來(lái)會(huì)怎么發(fā)展屏箍。在這里绘梦,我想談一下對(duì) Scala 和 Clojure 的設(shè)計(jì)者的看法橘忱。
Scala 的設(shè)計(jì)者 Martin Odersky,雖然在程序語(yǔ)言領(lǐng)域有所建樹(shù)谚咬,發(fā)表了不少看似高深的學(xué)術(shù)論文( 其實(shí)很多是扯淡的)鹦付,然而他對(duì)于語(yǔ)言的“設(shè)計(jì)”尚粘,其實(shí)并不是特別在行择卦。所以我很驚訝的發(fā)現(xiàn),有些非忱杉蓿基本的東西秉继,Scala 都會(huì)搞錯(cuò)。由于 Odersky 是大學(xué)教授泽铛,名聲在外尚辑,很多人想找他拿個(gè) PhD,所以東拉西扯的盔腔,喜歡往 Scala 里面加入一些不明不白杠茬,有潛在問(wèn)題的“特性”,其目的就是發(fā) paper弛随,混畢業(yè)瓢喉。這導(dǎo)致 Scala 過(guò)度繁復(fù),加入的特性很多后來(lái)被證明沒(méi)有多大用處舀透,反而帶來(lái)了問(wèn)題栓票。學(xué)生把代碼實(shí)現(xiàn)加入到 Scala 的編譯器,畢業(yè)就走人不管了愕够,所以 Scala 編譯器里走贪,就留下一堆堆的歷史遺留垃圾和 bug。
再來(lái)說(shuō)一下 Clojure惑芭。當(dāng) Clojure 最初“橫空面世”的時(shí)候坠狡,有些人熱血沸騰地向我推薦。于是我看了一下它的設(shè)計(jì)者 Rich Hickey 做的宣傳講座視頻遂跟。當(dāng)時(shí)我就對(duì)他一知半解拍胸脯的本事擦秽,印象非常的深刻。Rich Hickey 真的是半路出家漩勤,連個(gè) CS 學(xué)位都沒(méi)有感挥。可他那種氣勢(shì)越败,仿佛其他的語(yǔ)言設(shè)計(jì)者什么都不懂触幼,只有他看到了真理似的。不過(guò)也只有這樣的人究飞,才能創(chuàng)造出“宗教”吧置谦?Clojure 大力宣傳的“特性”(什么 lazy 啊堂鲤,pure 啊,transactional memory 懊较俊)瘟栖,都是從別的語(yǔ)言道聽(tīng)途說(shuō)抄過(guò)來(lái),卻又沒(méi)能深刻理解其精髓谅阿。有些“函數(shù)式語(yǔ)言”的特性半哟,本來(lái)就是有問(wèn)題的,卻不問(wèn)青紅皂白签餐,為了“主義正確”寓涨,抄過(guò)來(lái)。所以最后你發(fā)現(xiàn)這語(yǔ)言是掛著羊頭賣(mài)狗肉氯檐,說(shuō)得頭頭是道戒良,用起來(lái)怎么就那么蹩腳。
Clojure 的社區(qū)冠摄,一直忙著從 Scheme 和 Racket 的社區(qū)抄襲思想糯崎,卻又想標(biāo)榜是自己的發(fā)明。比如 Typed Clojure河泳,就是原封不動(dòng)抄襲 Typed Racket蛉签。有些一模一樣的基本概念冯键,在 Scheme 里面都幾十年了拢军,恁是要改個(gè)不一樣的名字逢倍,免得你們發(fā)現(xiàn)那是 Scheme 先有的。甚至有人把 SICP竿刁,The Little Schemer 等名著里的代碼黄锤,全都用 Clojure 改寫(xiě)一遍,結(jié)果完全失去了原作的簡(jiǎn)單性和精華性食拜。最后你發(fā)現(xiàn)鸵熟,Clojure 里面好的地方,全都是 Scheme 已經(jīng)有的负甸,Clojure 里面新的特性流强,幾乎全都有問(wèn)題。我參加過(guò)一些 Clojure 的 meetup呻待,可是后來(lái)發(fā)現(xiàn)打月,里面竟是各種喊著大口號(hào)的初學(xué)者,各種趾高氣昂的民科蚕捉,愚昧之至奏篙。
盲目推崇 Scala 和 Clojure 的人們,很多最后都發(fā)現(xiàn),這些語(yǔ)言里面的“新特性”秘通,幾乎都有毛病为严。它們里面最重要最有用的特性,其實(shí)早就已經(jīng)在 Java 里了肺稀。有些人跟我說(shuō):“你看第股,Java 做不了這件事情!” 后來(lái)經(jīng)我分析话原,發(fā)現(xiàn)他們?cè)跐撘庾R(shí)里早已死板的認(rèn)定夕吻,非得用某種最新最酷的語(yǔ)言特性,才能達(dá)到目的稿静。Java 沒(méi)有這些特性梭冠,他們就以為 Java 做不了辕狰,非得用另外的語(yǔ)言改备。其實(shí)蔓倍,如果你換一個(gè)角度來(lái)看問(wèn)題偶翅,不要鉆牛角尖母剥,專注于解決問(wèn)題朵耕,而不是去追求最新最酷的“寫(xiě)法”伪阶,你就能用 Java 解決它栅贴,而且解決得干凈利落癣缅。
如果現(xiàn)在要做一個(gè)系統(tǒng)陶衅,真的寧可用 Java勇皇,也不要浪費(fèi)時(shí)間去折騰什么 Scala 或者 Clojure门烂。錯(cuò)誤的人設(shè)計(jì)了錯(cuò)誤的語(yǔ)言慨丐,拿出來(lái)浪費(fèi)大家的時(shí)間。
Java 沒(méi)有特別討厭的地方
Java 也許缺少一些方便的特性斩松,然而長(zhǎng)久以來(lái)用 Java 進(jìn)行教學(xué)乳幸,用 Java 工作,用 Java 開(kāi)發(fā) PySonar钧椰,RubySonar粹断,Yin 語(yǔ)言,…… 我發(fā)現(xiàn) Java 其實(shí)并不像很多人傳說(shuō)的那么可惡嫡霞。我發(fā)現(xiàn)自己想要的 95% 以上的功能瓶埋,在 Java 里面都能找到比較直接的用法。剩下的5%,用稍微笨一點(diǎn)的辦法养筒,一樣可以解決問(wèn)題曾撤。
很多人討厭 Java,其實(shí)是因?yàn)樵缙诘?GoF Design Patterns晕粪,試圖提出千篇一律的模板挤悉,給程序帶來(lái)了不必要的復(fù)雜性。然而 Java 語(yǔ)言本身巫湘,其實(shí)跟 Design Patterns 并不是等價(jià)的装悲。Java 的設(shè)計(jì)者跟 Design Pattern 的設(shè)計(jì)者,完全是不同的人尚氛。你完全可以使用 Java 寫(xiě)出非常簡(jiǎn)單的代碼诀诊,而不使用 Design Patterns。
Java 有優(yōu)秀的 IDE 支持
我平時(shí)都用 IntelliJ 來(lái)寫(xiě) Java 代碼阅嘶。我發(fā)現(xiàn) IntelliJ 里面属瓣,有一些非常好的設(shè)計(jì)思想。其中很多功能奈懒,其實(shí)超越了所有的文本編輯器(Emacs奠涌,VIM……)宪巨。IntelliJ 讓 Java 如虎添翼磷杏,開(kāi)發(fā)起來(lái)感覺(jué)是在飛一樣。
用 IntelliJ 的時(shí)候捏卓,你不需要為“給變量起名字”之類(lèi)的事情焦慮极祸。因?yàn)?IntelliJ 有非常強(qiáng)大而友好的 refactor 功能,你可以非常迅速的換掉變量的名字怠晴。所以在第一次創(chuàng)造變量的時(shí)候遥金,你不需要花心思去起一個(gè)完美的名字。用一個(gè)還算湊合的名字蒜田,把代碼很快寫(xiě)出來(lái)稿械,實(shí)驗(yàn)成功。然后再返回去看代碼冲粤,把名字換成一個(gè)更合適的就可以美莫。
IntelliJ 還可以進(jìn)行非常迅速的結(jié)構(gòu)變換,這讓你就像藝術(shù)家在構(gòu)造一個(gè)雕塑作品梯捕。最開(kāi)頭我可以大刀闊斧厢呵,把代碼劈成大致的形狀,然后再把它仔細(xì)推敲傀顾,揉捏成更好襟铭,更容易理解,更具魅力的形狀。
結(jié)論
我實(shí)在不忍心看著有些人被 Scala 和 Clojure 忽悠寒砖。如果沒(méi)有超級(jí)高的性能和資源需求(可能要用C這樣的低級(jí)語(yǔ)言)赐劣,目前我建議就老老實(shí)實(shí)用 Java 吧。雖然不如一些新的語(yǔ)言炫酷哩都,然而實(shí)際的系統(tǒng)隆豹,還真沒(méi)有什么是 Java 寫(xiě)不出來(lái)的。少數(shù)地方可能需要繞過(guò)一些限制茅逮,或者放寬一些要求璃赡,然而這樣的情況不是很多。
編程使用什么工具是重要的献雅,然而工具終究不如自己的技術(shù)重要碉考。很多人花了太多時(shí)間,折騰各種新的語(yǔ)言挺身,希望它們會(huì)奇跡一般的改善代碼質(zhì)量侯谁,結(jié)果最后什么都沒(méi)做出來(lái)。選擇語(yǔ)言最重要的條件章钾,應(yīng)該是“夠好用”就可以墙贱,因?yàn)轫?xiàng)目的成功最終是靠人,而不是靠語(yǔ)言贱傀。