Effective.Java第23-33条(泛型相关)
23.? 類結(jié)構(gòu)層次優(yōu)于標(biāo)簽類
? 有時你會碰到一個類,它的實例有一個或多個風(fēng)格,并且包含一個tag屬性表示實例的風(fēng)格。例如,如下面的類表示一個圓或者矩形:
public class Figure {/*** 標(biāo)簽: circle表示圓 rectangle表示矩形*/private String tag;private double length;private double width;private double radis;public Figure(double radis) {super();this.radis = radis;}public Figure(double length, double width) {super();this.length = length;this.width = width;}public double area() {// 返回圓的面積if ("circle".equals(tag)) {return Math.PI * radis * radis;}if ("rectangle".equals(tag)) {return length * width;}return 0;}?
這樣的類有很多缺點,代碼可讀性查,將來增加一個三角形又得重寫計算面積的方式,而且需要增加三角形屬性。
?
解決辦法,用類層次結(jié)構(gòu)代替:
package cn.qlq;public abstract class Figure {abstract double area(); }class Circle extends Figure {private double radis;@Overridedouble area() {return Math.PI * radis * radis;}}class Rectangle extends Figure {private double length;private double width;@Overridedouble area() {return length * width;}}?
24.? 支持使用靜態(tài)成員類而不是非靜態(tài)類
有四種嵌套類:靜態(tài)成員類、非靜態(tài)成員類、匿名內(nèi)部類和局部類。
靜態(tài)成員類是最簡單的嵌套類。最好把它看做是一個普通的類,恰好在另一個類中聲明,并且可以訪問宿主類的成員,甚至是那些被聲明為私有類的成員。其一個主要用途是作為公共幫助類,例如Calculator可以使用Calculator.Operation.PLUS。
在語法上,靜態(tài)成員和非靜態(tài)成員類之間的唯一區(qū)別是靜態(tài)成員類在其宿主類中用static修飾。
如果聲明了一個不需要訪問宿主實例的成員類,不如用static修飾使之成為靜態(tài)成員類。
?
25.? 將源文件限制為單個頂級類
雖然Java編譯器允許在單個Java文件中定義多個頂級類,只需要文件名與public修飾的類一致即可,但是不建議這么做。
?
26.? 不要使用原始類型
也就是泛型盡量指明類型,雖然存在泛型擦除,但是至少編譯期間會減少一些潛在的錯誤。比如你很容易將BigInteger和BigDecimal存入同一個集合。
比如下面就是正確的用法:(右邊直接用<>即可,編譯器會自動推斷出正確的實際類型參數(shù),不寫<>會編譯警告)
Map<String, Object> result = new HashMap<>();?
?泛型的術(shù)語如下:
?
27.? 消除非檢查警告
? 盡可能的消除每一個未經(jīng)檢查的警告。
如果不能消除警告,但你確保證明引發(fā)警告的代碼是類型安全的,那么只能用@SuppressWarnings("unused")來消除警告(注意使用注解壓制警告的時候?qū)懨髟?。
總之,未經(jīng)檢查的警告是重要的,在運行時可能會出現(xiàn)ClassCaseException異常。
比如:
List<String> list = new ArrayList();會有一個警告:ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized
?
寫成下面這樣則不會出現(xiàn)警告,雖然右邊只是一個<>符號,并沒有指定真正的實際類型參數(shù),但編譯器會根據(jù)前面的自動推斷。
List<String> list = new ArrayList<>();?
?28.? 列表優(yōu)于數(shù)組
? 列表與數(shù)組在兩方面不同。
首先,數(shù)組是斜變的,也就是如果Sub是Super的子類,則數(shù)組類型Sub[]是Super[]的子類型;集合是不變的,對于任何兩種不同的類型Tyepe1和Type2,List<Type1>既不是List<Type2>的子類型也不是父類型。
也就是說:如下編譯不通過
// 正確編譯Object[] objects = new Long[11];?
如下會報編譯錯誤:
// 編譯不通過List<Object> lists = new ArrayList<Long>();?
? 第二個差異就是數(shù)組被具體化了,也就是數(shù)組在運行時知道并強制執(zhí)行它們的元素類型。如果嘗試將String放入一個Long型數(shù)組是做不到的,但是通過集合不指定具體的實際類型卻可以做到。
?
由于上面的差異,數(shù)組和泛型不能很好的結(jié)合在一起。例如,創(chuàng)建泛型類型的數(shù)組,參數(shù)化類型的數(shù)組以及類型參數(shù)的數(shù)組都是非法的。因此,這些數(shù)組創(chuàng)建表達(dá)式都不合法:
new List<E>();new List<String>();new E<String>();?
補充:Java語言并不支持列表,所以一些泛型類型(如ArrayList)必須在數(shù)組上實現(xiàn),其他的泛型類型,比如HashMap是為了提高性能而實現(xiàn)的。
?
29.? 優(yōu)先考慮泛型
泛型類型比需要在客戶端代碼中強制轉(zhuǎn)換的類型更安全,更易于使用。當(dāng)你設(shè)計新的類型時,確保它們可以在沒有這種強制轉(zhuǎn)換的情況下使用。這通常意味著使類型泛型化。
如果有任何現(xiàn)有的類型應(yīng)該是泛型化但實際上卻不是,考慮把它們泛型化。這使得這些類型的新用戶的使用更容易,而不會破壞現(xiàn)有的客戶端。
30.? 優(yōu)先使用泛型方法
泛型類和泛型方法需要選擇的時候優(yōu)先使用泛型方法。
?
31.? 使用限定通配符來增加API的靈活性(重要)
參數(shù)化類型是不變的。比如List<String> 你就只能存放String類型的數(shù)據(jù)。
相對于提供的不可變的類型,有時候使用限定通配符可以獲得更高的靈活性。
在API中使用通配符類型很棘手,但使得API更加靈活。一條基本的原則就是producer-extends,consumer-super(PECS)。還需要記住,所有Comparable和Comparator都是消費者。如果一個輸入?yún)?shù)同時是生產(chǎn)者和消費者那么考慮使用精確類型。
如下:
package cn.qlq;import java.util.ArrayList; import java.util.List;public class Client {public static void main(String[] args) {List<Integer> set1 = new ArrayList<>();set1.add(1);List<Float> set2 = new ArrayList<>();set2.add(1F);List<Number> unionMember = unionMember(set1, set2);System.out.println(unionMember);}private static <E> List<E> unionMember(List<? extends E> set1, List<? extends E> set2) {List<E> result = new ArrayList<>();result.addAll(set1);result.addAll(set2);return result;}}上面的unionMember方法的參數(shù)聲明,兩個參數(shù)set1和set2都是E的生產(chǎn)者所以PCES告訴我們應(yīng)該用extends。
請注意:返回類型仍然是E,不要使用限定通配符作為返回類型。
?
32.? 合理地結(jié)合泛型和可變參數(shù)
一般不要同時使用可變的泛型參數(shù)。
?
33.? 優(yōu)先考慮類型安全的異構(gòu)容器
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/qlqwjy/p/11049475.html
總結(jié)
以上是生活随笔為你收集整理的Effective.Java第23-33条(泛型相关)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

- 上一篇: Linux常用命令——压缩与解压缩命令
- 下一篇: jquery实现页面导航列表点击添加ac