Dustin Marx是一位專業軟件開發者,從業已經有17年的時間,他擁有電子工程學士學位,仍是一位MBA。Dustin維護着一個博客,專門介紹軟件開發的各個 主題。近日,他撰文談到了Java開發中常見的危險信號,提出了在平常的Java開發中咱們須要盡力避免的一些不正確的作法。html
通過多年的開發、閱讀、回顧並維護了數萬行的Java代碼後,我常常會看到Java代碼中 出現的某些「危險信號」,這些信號常常(但也許並不老是)暗示着代碼出現了某些問題。我這裏所要談的並非那些老是錯誤的實踐,而是想要談談在某些場景下 多是恰當,但一般卻會致使問題的一些實踐。這些「危險信號」有時可能並無問題,但卻會形成問題的積累,並最終致使問題的產生。這裏我總結出了一些「危 險信號」,而且談談在哪些狀況下他們是沒有問題的,在哪些狀況下則會致使問題。緩存
這裏將要談及的不少「危險信號」一般都會收到來自於FindBugs等代碼分析工具所發出的警告信息,流行的Java IDE也會將它們標記出來。不過,我發現有很多開發者會忽略掉這些來自於工具與IDE的警告信息,要麼是由於他們關掉了提示信息,要麼是出於自身的開發習 慣或是不理解與這些警告信息所關聯的風險,所以會忽略掉警告信息。安全
對引用使用==(而不是.equals)工具
不少Java開發者都知道使用==比較原生類型數據,使用.equals比較引用類型數據。這是一條很容易記住的簡單原則,Java開發者這麼 用也沒什麼問題。有時使用==來比較標準的Java類型引用(String、Integer、Long等等)也沒問題,不過這要取決於被緩存的值的大小, 所以這麼作並非一個好的作法。有時,咱們須要檢查標識的相等性而不是內容的相等性,在這種狀況下使用==來比較引用就很適合了。相對而言,我更喜歡 Groovy的處理方式,==相似於.equals,而===則是更加嚴格地比較標識。同理,使用!=來比較兩個引用也是一個「危險信號」,由於若是待比 較的兩個對象不共享相同的標識(內存地址),即使他們擁有相同的內容也老是會返回true。性能
對枚舉使用.equals(而不是==)單元測試
坦率地說,對於枚舉,Java開發者使用==仍是.equals都沒有太大關係。不過,我更傾向於對枚舉使用==。這麼作最重要的緣由就是對枚 舉使用==能夠防止不當心將枚舉與不相關的對象進行比較(永遠不會相等)。Object.equals(Object)方法能夠接收任意對象,這意味着編 譯器並不會強制限定傳進來的對象要與被比較的對象是相同的類型。通常來講,我更喜歡靜態的編譯期問題檢測而非動態運行期的問題檢測,對枚舉使用==能夠滿 足這個要求。同理,在比較枚舉時,!=與!.equals也是同樣的。測試
魔數與字符串字面值spa
我常常會在Java代碼中看到有人使用「魔數」和字符串字面值。他們對於將來的維護來講是一種「危險信號」,讓我十分懷疑應用的正確性。在單個 位置處將其標識爲常量(若是可能用枚舉來表示更佳),這麼作能夠改善將來的維護,而且讓我能夠更加自信地相信使用這些值的全部代碼都在使用着相同的值。除 此以外,在一個地方定義好常量與枚舉能夠更方便地使用IDE的「查找使用」特性來找到全部使用這些常量的地方。設計
字符串常量htm
在看到有限的相關字符串常量時,我就在想使用枚舉應該更加適合。對於高度內聚的字符串常量的狀況來講更是如此,由於枚舉能夠更好地表達出這些字 符串所表示的概念。相比於字符串常量來講,枚舉提供了編譯期的靜態類型安全與潛在的性能優點。對於程序的正確性來講,編譯期的安全是最吸引個人地方。
使用Java的「goto」
不多有人會使用標籤代碼,若是使用了那也說明用法不當。換句話說,若是使用了也是濫用而已。在大多數狀況下,使用Java的「goto」會形成代碼的可讀性極差。
根據做用域來肯定恰當的變量引用
我認爲這種方式永遠都是不恰當的,但它卻能運行,甚至有時是被某些Java開發者有意而爲之。好比說,Java開發者 將傳遞進方法的變量在方法執行時指向了另外一個引用。該變量(臨時指向方法參數)指向了另外一個引用,直到方法結束爲止,這時它脫離了做用域。在這種狀況下, 在方法簽名的參數定義前加上final關鍵字會致使編譯器錯誤,這也是我喜歡在方法參數前加上final的緣由之一。對於我來講,在方法中聲明一個新的局 部變量是更加清晰且可讀的方式,由於它只能在方法中使用。更爲重要的是,做爲代碼的讀者,我不知道是開發者有意但願該參數名只是指向一個不一樣的值仍是引入 了Bug,由於將參數從新指向新的引用實際上會改變調用端的值。若是我看到有人這麼寫,那麼我就會找代碼的編寫者或是經過單元測試來驗證代碼的意圖。
equals(Object)與hashCode()方法的不匹配
雖然我認爲每一個Java類都應該重寫toString()方法,但對於equals(Object)與hashCode()方法來講卻並不這麼 認爲。我以爲只有在須要這些方法的場合下才應該重寫類中的這兩個方法,由於他們的存在暗示着其設計與開發某種程度上的徹底改變。特別地,equals與 hashCode方法要能知足其意圖與契約(位於Object類的API文檔),而且須要保持一致。大多數IDE與分析工具都會在其中一個方法重寫而另外一 個沒有重寫的狀況下給出提示。然而,我要確保equals與hashCode使用的是相同的屬性,而且在這兩個方法中屬性的順序要保持一致。
本文轉自: http://www.spasvo.com/news/html/2013121895528.html