国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Effective Java

2019-11-14 22:34:25
字體:
來源:轉載
供稿:網友
Effective java - 用靜態工廠方法代替構造器

Effective Item - 考慮用靜態工廠方法代替構造器我們有兩種常見的方法獲得一個類的實例:

  • 公有的構造器
  • 提供靜態工廠方法(static factory method)

相對公有的構造器,靜態工廠方法有以下幾大優勢。

優勢1.靜態工廠方法的名稱,因此比構造器更準確地描述返回的實例。比如BigInteger.PRobablePrime方法:

public static BigInteger probablePrime(int bitLength, Random rnd) {    if (bitLength < 2)        throw new ArithmeticException("bitLength < 2");    // The cutoff of 95 was chosen empirically for best performance    return (bitLength < SMALL_PRIME_THRESHOLD ?            smallPrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd) :            largePrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd));}

順便也貼出其調用的largePrime方法:

private static BigInteger largePrime(int bitLength, int certainty, Random rnd) {    BigInteger p;    p = new BigInteger(bitLength, rnd).setBit(bitLength-1);    p.mag[p.mag.length-1] &= 0xfffffffe;    // Use a sieve length likely to contain the next prime number    int searchLen = (bitLength / 20) * 64;    BitSieve searchSieve = new BitSieve(p, searchLen);    BigInteger candidate = searchSieve.retrieve(p, certainty, rnd);    while ((candidate == null) || (candidate.bitLength() != bitLength)) {        p = p.add(BigInteger.valueOf(2*searchLen));        if (p.bitLength() != bitLength)            p = new BigInteger(bitLength, rnd).setBit(bitLength-1);        p.mag[p.mag.length-1] &= 0xfffffffe;        searchSieve = new BitSieve(p, searchLen);        candidate = searchSieve.retrieve(p, certainty, rnd);    }    return candidate;}

雖然smallPrime和largePrime最后都是通過公有構造器返回實例。但是如果僅僅用構造器重載表達這個實例的特征,這很難讓人記住什么時候應該調用什么構造器。而提供一個名稱去描述實例更為直觀。

優勢2.靜態工廠方法不必每次都創建一個新的對象,我們可以對實例進行控制。這樣我們就能將創建好的實例緩存起來重復利用,尤其是在創建對象的代價較高的情況下。比如Boolean.valueOf:

public static final Boolean TRUE = new Boolean(true);public static final Boolean FALSE = new Boolean(false);public static Boolean valueOf(boolean b) {    return (b ? TRUE : FALSE);}

優勢3.靜態工廠方法可以返回原返回類型的子類型對象。這一點能體現靜態工廠方法的靈活性,以EnumSet為例:

/** * Creates an empty enum set with the specified element type. * * @param elementType the class object of the element type for this enum *     set * @throws NullPointerException if <tt>elementType</tt> is null */public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {    Enum[] universe = getUniverse(elementType);    if (universe == null)        throw new ClassCastException(elementType + " not an enum");    if (universe.length <= 64)        return new RegularEnumSet<>(elementType, universe);    else        return new JumboEnumSet<>(elementType, universe);}

而RegularEnumSet和JumboEnumSet為EnumSet的子類,并且都沒有提供公有構造器。

優勢4.靜態工廠方法創建參數化(泛型)實例的時候更加簡潔。舉個例子:

public static <K, V> HashMap<K, V> newInstance() {    return new HashMap<K, V>();}

這樣一來創建實例時就可以:

Map<String,List<Integer>> n = newInstance();

而不是

Map<String,List<Integer>> m = new HashMap<String,List<Integer>>();

從Java7開始這一點變得沒有意義,事實上Josh Bloch也在書上提到了這點——Java以后會在構造器和方法調用中執行這種類型推導。

說說靜態工廠方法的缺點。

  • 類如果不含公有或者受保護的構造器就不能被子類化。所以上面說的靜態工廠方法可以返回原返回類型的子類型對象。并不完全正確。雖然我們可以通過復合方式(composition)解決這一問題,但這樣兩個類就不是is-a關系了。
  • 靜態工廠方法的本質還是靜態方法,他沒有一個特別的標準。我們無法在API文檔中把一個靜態工廠方法特別標識出來(也許可以加個標準annotation?)。當我要從API中找一個方法去實例化一個類時,相對構造器而言還是不夠直觀。雖然沒有特個特別的標準,但我們也可以用標準的命名來彌補一點點。比如valueOf,getInstance,newInstance,newType等...

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 高碑店市| 平遥县| 宁国市| 马鞍山市| 鄄城县| 宝山区| 稻城县| 武汉市| 威宁| 当阳市| 乐业县| 开封县| 颍上县| 揭阳市| 商丘市| 宁陵县| 兰溪市| 宜春市| 濮阳市| 东辽县| 开化县| 兴宁市| 阿巴嘎旗| 青海省| 海伦市| 新建县| 渑池县| 吉安市| 连州市| 商丘市| 胶州市| 宁德市| 彰化市| 镇雄县| 临夏县| 内乡县| 渭源县| 秦皇岛市| 崇仁县| 柞水县| 六盘水市|