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