Tips
《Effective Java, Third Edition》一書英文版已經出版,這本書的第二版想必不少人都讀過,號稱Java四大名著之一,不過第二版2009年出版,到如今已經將近8年的時間,但隨着Java 6,7,8,甚至9的發佈,Java語言發生了深入的變化。
在這裏第一時間翻譯成中文版。供你們學習分享之用。java
使用泛型編程時,會看到許多編譯器警告:未經檢查的強制轉換警告,未經檢查的方法調用警告,未經檢查的參數化可變長度類型警告以及未經檢查的轉換警告。 你使用泛型得到的經驗越多,得到的警告越少,但不要指望新編寫的代碼可以乾淨地編譯。編程
許多未經檢查的警告很容易消除。 例如,假設你不當心寫了如下聲明:安全
Set<Lark> exaltation = new HashSet();
編譯器會提醒你你作錯了什麼:學習
Venery.java:4: warning: [unchecked] unchecked conversion Set<Lark> exaltation = new HashSet(); ^ required: Set<Lark> found: HashSet
而後能夠進行指示修正,讓警告消失。 請注意,實際上並不須要指定類型參數,只是爲了代表它與Java 7中引入的鑽石運算符("<>")一同出現。而後編譯器會推斷出正確的實際類型參數(在本例中爲Lark):ui
Set<Lark> exaltation = new HashSet<>();
但一些警告更難以消除。 本章充滿了這種警告的例子。 當你收到須要進一步思考的警告時,堅持不懈! 儘量地消除每個未經檢查的警告。 若是你消除全部的警告,你能夠放心,你的代碼是類型安全的,這是一件很是好的事情。 這意味着在運行時你將不會獲得一個ClassCastException異常,而且增長了你的程序將按照你的意圖行事的信心。翻譯
若是你不能消除警告,但你能夠證實引起警告的代碼是類型安全的,那麼(而且只能這樣)用@SuppressWarnings(「unchecked」)
註解來抑制警告。 若是你在沒有首先證實代碼是類型安全的狀況下壓制警告,那麼你給本身一個錯誤的安全感。 代碼可能會在不發出任何警告的狀況下進行編譯,可是它仍然能夠在運行時拋出ClassCastException異常。 可是,若是你忽略了你認爲是安全的未經檢查的警告(而不是抑制它們),那麼當一個新的警告出現時,你將不會注意到這是一個真正的問題。 新出現的警告就會淹沒在全部的錯誤警告當中。code
SuppressWarnings
註解可用於任何聲明,從單個局部變量聲明到整個類。 始終在儘量最小的範圍內使用SuppressWarnings
註解。 一般這是一個變量聲明或一個很是短的方法或構造方法。 切勿在整個類上使用SuppressWarnings
註解。 這樣作可能會掩蓋重要的警告。blog
若是你發現本身在長度超過一行的方法或構造方法上使用SuppressWarnings
註解,則能夠將其移到局部變量聲明上。 你可能須要聲明一個新的局部變量,但這是值得的。 例如,考慮這個來自ArrayList的toArray方法:ip
public <T> T[] toArray(T[] a) { if (a.length < size) return (T[]) Arrays.copyOf(elements, size, a.getClass()); System.arraycopy(elements, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } 若是編譯ArrayList類,則該方法會生成此警告: ArrayList.java:305: warning: [unchecked] unchecked cast return (T[]) Arrays.copyOf(elements, size, a.getClass()); ^ required: T[] found: Object[]
在返回語句中設置SuppressWarnings
註解是非法的,由於它不是一個聲明[JLS,9.7]。 你可能會試圖把註釋放在整個方法上,可是不要這要作。 相反,聲明一個局部變量來保存返回值並標註它的聲明,以下所示:element
// Adding local variable to reduce scope of @SuppressWarnings public <T> T[] toArray(T[] a) { if (a.length < size) { // This cast is correct because the array we're creating // is of the same type as the one passed in, which is T[]. @SuppressWarnings("unchecked") T[] result = (T[]) Arrays.copyOf(elements, size, a.getClass()); return result; } System.arraycopy(elements, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }
所產生的方法乾淨地編譯,並最小化未經檢查的警告被抑制的範圍。
每當使用@SuppressWarnings(「unchecked」)
註解時,請添加註釋,說明爲何是安全的。 這將有助於他人理解代碼,更重要的是,這將減小有人修改代碼的可能性,從而使計算不安全。 若是你以爲很難寫這樣的註釋,請繼續思考。 畢竟,你最終可能會發現未經檢查的操做是不安全的。
總之,未經檢查的警告是重要的。 不要忽視他們。 每一個未經檢查的警告表明在運行時出現ClassCastException異常的可能性。 盡你所能消除這些警告。 若是沒法消除未經檢查的警告,而且能夠證實引起該警告的代碼是安全類型的,則能夠在儘量小的範圍內使用 @SuppressWarnings(「unchecked」)
註解來禁止警告。 記錄你決定在註釋中抑制此警告的理由。