介紹
在我看來,這篇文章提出了Java語言應該如何發展以保持其作為首選語言的地位。 它還提供了一些我喜歡但有時(可能永遠不會)成為Java一部分的功能,由于我將要解釋的某些原因,這些功能有時我已經愛上了。 我真的很想一天將其中一些想法轉換為JSR。
在過去的15年中,Java語言和JVM得到了極大的改進。 JIT編譯器,泛型的應用,自動裝箱,很快(指尖)的lambda……所有這些功能都為Java的成功做出了貢獻。 但是接下來呢? 如何使Java更好?
通過我的經驗,我有機會使用幾種編程語言。 其中包括C#,C / C ++,PHP,Javascript,Groovy,ActionScript 3,Scala等。在許多這些語言中,我發現了一些使我說“真棒!”的功能。 其中一些功能不適用于Java(不同的編程范例,不同的思維方式),而另一些則完全適用。 同樣在其中一些語言中(主要是PHP),我看到了讓我說“ OMG! 真是胡扯!”……但這是一個不同的故事!
在該系列的每一部分中,我將介紹一個Java中不存在的功能,并解釋為什么它應該(或不應該)在Java中,可能要解決的問題,等等。
不要猶豫,發布改進的想法,甚至是最瘋狂/不切實際的想法! 我并不假裝自己有完美的解決方案,我只是嘗試打開討論。
屬性訪問器
在我看來,這篇文章提出了Java語言應該如何發展以保持其作為首選語言的地位。 它還提供了一些我喜歡但有時(可能永遠不會)成為Java一部分的功能,由于我將要解釋的某些原因,這些功能有時我已經愛上了。 我真的很想一天將其中一些想法轉換為JSR。
通過透明訪問器訪問對象的字段絕對是我在Java中缺少的功能。
它是什么?
在Java中,我們使用getter和setter來訪問對象的屬性。 我不會說擁有getter和setter而不是擁有公共字段的好處,我假設您已經意識到……在其他語言(C#,AS3,…)中,您可以顯式聲明屬性的getter和setter。就像使用公共財產一樣使用它們。 我最喜歡的語法是一種ActionScript3:
//Object Declaration
public class MyObject {private var _myProperty:String;public function get myProperty():String {return _myProperty;}public function set myProperty(value:String):void {_myProperty = value;}public function get firstLetter():String {return _myProperty.substr(0,1);}
}//Usage
var o:MyObject = new MyObject();
o.myProperty = 'A value'; //Set the property using the setter
trace(o.myProperty); //Print the value return by the getter
trace(o.firstLetter); //Print 'A'
Java語法建議
由于我認為ActionScript 3語法非常方便,因此我認為Java語法應該非常相似。 這將需要添加新的修飾符 : get
和set
。
public class MyObject
{private String _name;public get String name() {return name;}public set void name(String name) {this.name = name;}
}//Usage
MyObject o = new MyObject();
o.name = 'My name';
System.out.println('print entity : ' + o.name);
好處
- 使用訪問器是透明的。 封裝是隱式的。 調用者不知道它是在調用公共變量還是訪問器。
- 更好的OO風格編程:從外部類的角度來看,一個對象現在確實具有公共方法和屬性,而以前只是公共方法。
- 重構代碼以更改對對象字段的所有直接訪問實在是小菜一碟,您只需要更改相關的類即可,而不必更改所有的讀/寫調用。
- 不再需要在getter和setter上使用JavaBean約定。 有些庫依賴于
myProperty
器稱為[get|is|set]MyProperty
的事實。 現在,不再按約定定義承包人,而是按合同定義。 我們可以在Class
上有一個方法來檢索訪問器(getGetters(),getSetters())。 再次,大大提高了OOP。
缺點
- 由于方法和屬性的名稱可能相同,因此需要更改對象字段的命名約定。 毫無疑問,JVM可以允許屬性和方法具有相同的名稱,這更多是可讀性問題。
實施與問題
要實現此功能,需要向Java語言添加兩個新關鍵字( get
和set
)。 對于追溯兼容性而言,這是一件壞事,但這并不是一個大問題。 在Java 1.4中添加assert關鍵字之前,將需要使用“ -source”命令行選項。
此更改還需要修改JVM規范,以及Java編譯器,以添加兩個新的修飾符。 在類文件中需要使用這兩個新的修飾符,以便使用反射來標識類的getter和setter。
我相信此功能將對Java語言做出令人敬畏的改進。 作為所有重大改進,它需要大量工作。 如果有一天我有足夠的時間提交JSR,那肯定是這一天!
線程安全編譯檢查
在我看來,這篇文章提出了Java語言應該如何發展以保持其作為首選語言的地位。 它還提供了一些我喜歡但有時(可能永遠不會)成為Java一部分的功能,由于我將要解釋的某些原因,這些功能有時我已經愛上了。 我真的很想一天將其中一些想法轉換為JSR。
線程安全編譯檢查:這是什么?
它可以檢查您的程序是否不會由于多線程而出現問題。 據我所知,沒有一種編程語言提供此功能(如果您知道一種,請告訴我!)。
問題是什么?
開發在多個線程中運行的程序很容易,而開發不會有任何奇怪錯誤的東西,因為線程機制要困難得多。
為什么并發編程很難?
因為,要制作一個好的多線程應用程序,您必須非常小心并完全了解Java語言和API:避免出現死鎖,知道何時使用volatile關鍵字,知道什么是(或不是)線程安全的。
另一個困難是測試/調試多線程應用程序非常困難。 您可能花了幾天的時間想知道為什么在龐大的數據庫中,您的行中有一個奇怪的日期值……最終要認識到您的共同開發者(當然不是您,因為您是Java專家 )使用了多個線程共享的SimpleDateFormat對象……(順便說一句,如果您不知道:是的,SimpleDateFormat不是線程安全的)
解決辦法是什么?
線程安全編譯檢查! 如果有警告告訴您“在第36行:不是線程安全代碼”,它將使開發變得更加容易。 使用非線程安全方法SimpleDateFormat.format”。
為什么不可能
非線程安全API的用法
目前,了解所使用的庫/ API是否是線程安全的唯一方法是讀取Javadoc或源代碼。 因此,編譯器無法知道您調用的是線程安全的還是不線程安全的。 通過可傳遞性,如果您不使用任何種類的同步機制,則由于使用這些庫,因此無法知道您的代碼是否是線程安全的。
解決此問題的一種方法是創建一個@ThreadSafe注釋來注釋類和方法。 這樣,任何用@ThreadSafe注釋的元素都將被編譯器視為線程安全的。 當然,您使用的所有API都需要正確注釋。除了進行編譯檢查之外,我認為這樣的注釋對于使API更加清晰非常有用。
反射API
Reflection API是另一個問題。 由于執行流程是在運行時期間確定的,因此編譯器無法知道將調用哪些方法,因此無法確定將要執行的內容是否是線程安全的。
編譯器需要了解上下文
編譯器無法知道您正在開發的內容是否將在線程安全的環境中執行。 例如,如果您正在開發將由您最喜歡的CDI框架注入到各處的bean,則編譯器無法知道它。
換句話說,編譯器比您了解的少,因此無法確定您正在編程的內容是否需要線程安全。 假設您正在為J2EE應用程序編程控制器; 如果您不使用假設的@ThreadSafe注釋對控制器進行注釋,則編譯器將永遠不會抱怨。 問題是您的控制器必須是線程安全的! 如果您沒有使用@ThreadSafe正確注釋必須是線程安全的內容,那么您將遇到問題...
不同的鎖機制
如果同步線程的唯一方法是synced關鍵字,則對于編譯器而言,確定一段代碼是否可以同時運行比較容易。 不幸的是,事實并非如此! 您有幾種方法可以確保僅在正確的上下文中執行代碼( ReentrantLock , ReadWriteLock ,使用文件,套接字,對象,計數器等的手動鎖定)。 對我而言,這僅是導致“線程安全編譯檢查”無法實現的原因。 如果編譯器無法發現同步機制,則它對線程安全一無所知!
結論
線程安全編譯檢查肯定是一個殺手級功能。 但是對我來說,甚至不可能部分實現,這也許就是為什么我從未在任何語言中看到過此功能的原因。
如果您對解決方案有任何想法,或者您知道某種解決方案的語言(甚至是部分語言),請告訴我!
參考: Java SE 11:Java向前推進-第1部分: Java SE 11:Java向前推進-第2部分:屬性訪問器 , Java SE 11:Java Java向前推進-第3部分:來自我們JCG合作伙伴 Tibo Delor的線程安全編譯檢查在InvalidCodeException博客上。
翻譯自: https://www.javacodegeeks.com/2012/11/java-se-11-moving-java-forward.html