編程語言的未來,Java路在何方
英文原文:coderfriendly,編譯:王曉杰
我希望你有機會看看這個視頻“The future of the programming language”。這個會議是由C#的架構(gòu)師Anders Hejlsberg 主導(dǎo)的,視頻中他闡述了自己心目中的下一代編程語言應(yīng)該具備的主要特性:
特定領(lǐng)域語言(Domain Specific Language, 簡寫DSL,包括內(nèi)部及外部DSL)
有注解功能(將注意力集中在做什么而不是怎么做)
介于靜態(tài)語言好動態(tài)語言之間的語言
面向過程語言(命令式語言(Imperative Language)并不適合面向多線程編程)
他的演講非常棒,十分通俗易懂,從中我學(xué)到了很多,我相信微軟擁有世界上最好的實驗室。在演講的最后,他說他不理解為什么Java還沒有轉(zhuǎn)向面向過程。作為一名Java開發(fā)者,我不得不承認.net平臺確實非常強大。我喜歡他所倡導(dǎo)的”選一個自己喜歡的語言去編程吧!”
函數(shù)式編程
對于什么是函數(shù)式編程語言,Anders給出了一個很簡要的描述。例如,在命令式語言中,會經(jīng)常這么寫:
x=x+1
我們已經(jīng)按照這種方式編程很多年了,以至于我們幾乎忘了其他的一些科學(xué)家們并不是這樣做的。在數(shù)學(xué)領(lǐng)域,你應(yīng)該這么寫:
y=x+1
y的計算結(jié)果并不會改變x的值。這個例子可能有些過于簡單,為了進一步說明,我們來假設(shè)有這樣一個叫做”Number”的Java類。
- publicclassNumberImperative {
- privateint_value;
- publicNumberImperative(finalintvalue) {
- _value = value;
- }
- publicintgetValue(){
- return_value;
- }
- publicvoidadd(finalintnumberToAdd){
- _value += numberToAdd;
- }
- publicvoidsubstract(finalintnumberToSubstract){
- _value -= numberToSubstract;
- }
- }
以及第二種實現(xiàn):
- publicclassNumberFunctional {
- privatefinalint_value;
- publicNumberFunctional(finalintvalue) {
- _value = value;
- }
- publicintgetValue(){
- return_value;
- }
- publicNumberFunctional add(finalintnumberToAdd){
- returnnewNumberFunctional(_value + numberToAdd);
- }
- publicNumberFunctional substract(finalintnumberToSubstract){
- returnnewNumberFunctional(_value - numberToSubstract);
我知道你可能喜歡寫int y = x + 1;。但這個不是我們在這要討論的。這兩個例子中的代碼給出了命令式語言和函數(shù)式語言的最基本用法,我們使用下面這個段代碼來進行測試。
- publicfinalclassDemoNumber {
- publicstaticvoidmain(finalString[] args) {
- finalintx = 5;
- // imperative
- finalNumberImperative numberImperative = newNumberImperative(x);
- numberImperative.add(1);
- System.out.println("imperative: "+ numberImperative.getValue());
- // functional
- finalNumberFunctional numberFunctional = newNumberFunctional(x);
- finalNumberFunctional resultNumberFunctional = numberFunctional.add(1);
- System.out.println("functional: "+ resultNumberFunctional.getValue());
- }
- }
輸出的結(jié)果為:
我都能夠想象出你臉上的表情:”這哥們一定是個代碼控,這么喜歡寫代碼”。別忘了,這只是一個例子,而且在現(xiàn)實生活中我們不需要寫這樣的類 (NumberFunctional)。但是,如果你習(xí)慣于開發(fā)線程安全的代碼,那么你一定已經(jīng)意識到函數(shù)式的實現(xiàn)方式是不可變類,而不可變類可以很容易 的解決并行執(zhí)行過程中遇到的問題,JDK中有很多你可以隨時初始化的不可變類,例如:String,Integer,Double等。
在未來幾年,隨著多核微處理的普及,并行編程將成為開發(fā)人員必須要具備的核心競爭力。在NumberImperative類中,因為成員變量 “_value”是沒有同步的,所以在運行時將產(chǎn)生副作用。即便是我們對這個屬性進行了同步,但如果擁有同一個引用的兩個線程同時調(diào)用下面的函數(shù)的話,仍舊會形成競爭條件:
- publicvoidatomicProblem(finalNumberImperative numberImperative){
- if(numberImperative.getValue() == 0){
- numberImperative.add(1);
如果你讀過Brian Goetz的書“Java Concurrent in practice“,你可能會想到在你的代碼中加入Annotation。我們可以將NumberImperative類注解成 @NotThreadSafe,而將NumberFunctional類注解成@Immutable。
函數(shù)式語言默認就是不可更改的。如果我們想讓一個數(shù)據(jù)變得可以更改,我們需要追加一個關(guān)鍵字,比如: Closures,你可以參照Refs and Transactions。在F#語言中可以使用 mutable關(guān)鍵字,而在Scala中,可以用“var” 和 “val”這兩個關(guān)鍵字。
大勢所趨
目前我們所遇到的問題是,由于JCIP Annotation還不夠普及,構(gòu)建一個線程安全的軟件是十分困難的。就連一些Java標準類也沒有加入Annotation,如果你的團隊中的某些人沒有看過 Brian Goetz的書, 那么他/她很可能不知道如何編寫線程安全的類,如何使用Annotation。在我的團隊中,我總是認為那些沒有JCIP Annotation的類不是線程安全的。但是就連鼎鼎大名的Findbugs ,也無法幫你找出那些沒有加入Annotation的類。因此,要查找并發(fā)Bug是十分困難的。
那么,如何迫使程序員去適應(yīng)并發(fā)編程呢?我想我們不能要求所有的程序員去檢查他的程序是否存在并發(fā)的問題。我遇到過很多不喜歡讀書的程序員,因此JCIP相關(guān)的書籍也不是一個好的解決方案。Java是 James Gosling在 1995年創(chuàng)造的,那已經(jīng)是14年前的事情了?,F(xiàn)在我們發(fā)現(xiàn)要創(chuàng)建一個用Java寫的并發(fā)軟件的唯一方法就是,強化注解,并且對代碼用工具進行靜態(tài)分析。 但是你我都只知道,工具并不能使問題編程更簡單,只是讓他變得能夠管理。依我看來,想要迫使人們?nèi)W(xué)習(xí)新的方法論,一門新的語言是唯一的選擇。這樣程序員 就必須去學(xué)習(xí)新的內(nèi)容,去改變他們原有的習(xí)慣.
放棄Java?
就目前來看,答案當(dāng)然是否定的。Java非常的普及,龐大的社區(qū)需要很長時間才會接受新的編程語言.我想新的語言應(yīng)該是面向少數(shù)先知先覺者的,并且需要經(jīng)過多年的歷練才會崛起。一篇文章中這么寫道:最近確實有很多關(guān)于Java語言未來的博客,Daniel Weinreb強調(diào)“Java的普及率太高了,我們不太可能看到它消失”。同時,James Iry的觀點是“他目前是并且在未來很長一段時間內(nèi),都將是IT經(jīng)理為數(shù)不多的幾個最安全的選擇其中之一”。
因此,作為一個Java開發(fā)人員,我們需要豎起耳朵去聆聽市場的聲音,并且不斷地提高自己以便適應(yīng)未來五年內(nèi)可能發(fā)生的遷移。目前我們還是要現(xiàn)在工具編寫并發(fā)程序,因此我們需要繼續(xù)讀 Brian Goetz的書。并且在多線程場景中提高警惕。
那么你呢,你會給Java開發(fā)人員哪些建議?