成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

《Effective Java》學(xué)習(xí)筆記 第二章 創(chuàng)建和銷毀對象

tinylcy / 718人閱讀

摘要:第二章創(chuàng)建和銷毀對象何時以及如何創(chuàng)建對象,何時以及如何避免創(chuàng)建對象,如何確保他們能夠適時地銷毀,以及如何管理對象銷毀之前必須進行的各種清理動作。表示工廠方法所返回的對象類型。

第二章 創(chuàng)建和銷毀對象
何時以及如何創(chuàng)建對象,何時以及如何避免創(chuàng)建對象,如何確保他們能夠適時地銷毀,以及如何管理對象銷毀之前必須進行的各種清理動作。
1 考慮用靜態(tài)工廠方法代替構(gòu)造器
一般在某處獲取一個類的實例最常用的方法是提供一個共有的構(gòu)造器,還有一種方法,就是提供一個共有的靜態(tài)工廠(static factory method),他只是一個返回類的實例的靜態(tài)方法。

例:

 public static Boolean valueOf(boolean b){
     return b ? Boolean.TRUE:Boolean.FALSE;
 } 
注意,靜態(tài)工廠方法與設(shè)計模式中的工廠方法模式不同。類可以通過靜態(tài)工廠方法來提供給它的客戶端,而不是通過構(gòu)造器,提供靜態(tài)工廠方法而不是公有的構(gòu)造器,這樣做具有幾大優(yōu)勢:

靜態(tài)工廠方法,它們有名稱
例如構(gòu)造器BIgInteger(int,int,Random)返回的BigInteter可能為素數(shù),如果用名為BigInteger.probablePrime的靜態(tài)工廠方法來表示,顯然更為清楚。

不必在每次調(diào)用它們的時候都創(chuàng)建一個新的對象

這使得不可變類可以使用預(yù)先構(gòu)建好的實例,或者將構(gòu)建好的實例緩存起來,進行重復(fù)利用,從而避免常見不必要的重復(fù)對象,因為程序經(jīng)常請求創(chuàng)建相同的對象,那么創(chuàng)建對象的代價會很高。Boolean.valueOf(boolean)方法說明了這項技術(shù)。靜態(tài)工廠方法也經(jīng)常用于實現(xiàn)單例模式。

它們可以返回原返回類型的任何子類型的對象

靈活的靜態(tài)工廠方法構(gòu)成了服務(wù)提供者框架(Service Provider FrameWork)的基礎(chǔ),例如JDBC。

對于JDBC,Connection就是它的服務(wù)接口,DriverManager.registerDriver是提供者注冊API,DriverManager.getConnection是服務(wù)訪問API,Driver就是服務(wù)提供者接口。

例,下列簡單的實現(xiàn)包含了一個服務(wù)提供者接口和一個默認(rèn)提供者:

/**
 * Created by Newtrek on 2017/10/31.
 * 服務(wù)提供者接口
 */
public interface Provider {
//    提供服務(wù)實例,用服務(wù)接口返回
    Service newService();
}
/**
 * Created by Newtrek on 2017/10/31.
 * 服務(wù)接口
 */
public interface Service {
    // TODO: 2017/10/31  服務(wù)特有的方法 寫在這兒
}
/**
 * Created by Newtrek on 2017/10/31.
 */
public class Services {
//    構(gòu)造保護
    private Services(){}
//    provider映射表,保存注冊的Provider
    private static final Map providers=new ConcurrentHashMap<>();
//    默認(rèn)provider的名字
    public static final String DEFAULT_PROVIDER_NAME="";
//    注冊默認(rèn)的Provider
    public static void registerDefaultProvider(Provider p){
        registerProvider(DEFAULT_PROVIDER_NAME,p);
    }
//    注冊provider
    public static void registerProvider(String name,Provider p){
        providers.put(name,p);
    }

    /**
     * 靜態(tài)工廠方法返回Service實例
     */
    public static Service newInstance(){
        return newInstance(DEFAULT_PROVIDER_NAME);
    }
    public static Service newInstance(String name){
        Provider p = providers.get(name);
        if (p==null){
            throw new IllegalArgumentException("No provider registered with name:"+name);
        }
        return p.newService();
    }
}

在創(chuàng)建參數(shù)化類型實例的時候,它們是代碼變得更加簡潔

例:假設(shè)HashMap提供了這個靜態(tài)工廠

 public static  HashMap newInstance(){
     return new HashMap();
 } 

那么就可以用下面簡潔的代碼獲取實例了。

 Map> m=HashMap.newInstance(); 

把這些方法放在自己的工具類中是很實用的。不過現(xiàn)在java7,java8已經(jīng)實現(xiàn)了HashMap構(gòu)造的類型參數(shù)推測

缺點

類如果不含公有的或者受保護的構(gòu)造器,就不能被子類化

它們與其他的靜態(tài)方法實際上沒有任何區(qū)別

在API文檔中,它們沒有像構(gòu)造器那樣在API文檔中明確標(biāo)識出來,因為,對于提供了靜態(tài)工廠方法二不是構(gòu)造器的類來說,要想查明如何實例化一個類,這是非常困難的。可以通過在類或者接口注釋中關(guān)注靜態(tài)工廠,并遵守標(biāo)準(zhǔn)的命名習(xí)慣,可以彌補這一劣勢。下面是靜態(tài)工廠方法的一些慣用名稱。

valueOf:實際上是類型轉(zhuǎn)換方法。

of:valueOf的一種更為簡潔的代替

getInstance:返回的實例是通過方法的參數(shù)來描述的,但是不能夠說與參數(shù)具有同樣的值。對于Singleton來說,該方法沒有參數(shù),并返回唯一的實例。

newInstance:像getInstance一樣,但newInstance能夠確保返回的每個實例都與所有其它實例不同。

getType:像getInstance一樣,但是在工廠方法處于不同的類中的時候使用。Type表示工廠方法所返回的對象類型。

newType:像newInstance一樣,但是在工廠方法處于不同的類中的時候使用,Type表示工廠方法所返回的對象類型。

簡而言之,靜態(tài)工廠方法和公有構(gòu)造器都各有用處,我們需要理解他們各自的長處。靜態(tài)工廠通常更加合適,因此切忌第一反應(yīng)就是提供公有的構(gòu)造器,而不先考慮靜態(tài)工廠。
2.遇到多個構(gòu)造器參數(shù)時要考慮用構(gòu)建器
這個就是Builder設(shè)計模式
3.用私有構(gòu)造器或者枚舉類型強化Singleton屬性
這個是單例模式的注意事項,選擇最好的單例模式實現(xiàn)
4.通過私有構(gòu)造器強化不可實例化的能力
有時候需要編寫一些只包含靜態(tài)方法和靜態(tài)域的類,這些類的名聲很不好,因為有些人在面向?qū)ο蟮恼Z言中濫用這樣的類來編寫過程化的程序,盡管如此,他們也確實有它們的好處,比如常見的工具類java.lang.Math等,都是這樣。方正這樣不可以實例化的類,最好把他的構(gòu)造器設(shè)置為私有。

例如:

public class UtilityClass{
  private UtilityClass(){
      throw new AssertionError();
  }
}
5.避免創(chuàng)建不必要的對象

一般來說,最好能重用對象而不是再每次需要的時候就創(chuàng)建一個相同功能的新對象,如果對象是不可變的,他就始終可以被重用。
簡單的例子:字符串

String s = new String("stringtest");//不要這樣做,因為該語句每次執(zhí)行的時候都會創(chuàng)建一個新的String實例,沒必要
// 改進后的版本,這個版本只用了一個String實例,而不是每次執(zhí)行的時候都創(chuàng)建一個新的實例。對于再同一臺虛擬機中運行的代碼,只要它們包含相同的字符串自字面常量,該對象就可以被重用。
String s = "stringtest";

對于同時提供了靜態(tài)方法和構(gòu)造器方法的不可變類,通常可以使用靜態(tài)工廠方法而不是構(gòu)造器,以避免創(chuàng)建不必要的對象。

優(yōu)先使用基本類型,而不是裝箱基本類型,當(dāng)心無意識的自動裝箱。

也不要錯誤地認(rèn)為本條目暗示著“創(chuàng)建對象的代價非常昂貴,我們應(yīng)該盡可能地避免創(chuàng)建對象”,相反,由于小對象地構(gòu)造器制作很少量地顯示工作,所以,小對象地創(chuàng)建和回收動作是非常廉價地。

通過維護自己的對象池來避免創(chuàng)建對象比不是一種好的做法,除非池中的對象是非常重量級的,一般數(shù)據(jù)庫連接池常用。

6 消除過期的對象引用

不要以為Java有垃圾回收機制,能自動管理內(nèi)存,自動回收垃圾,就可以不管了,其實不然。
內(nèi)存泄漏的例子

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_CAPACITY = 16;

    public Stack(){
        elements = new Object[DEFAULT_CAPACITY];
    }

    public void push(Object object){
        ensureCapacity();
        elements[size++] = object;
    }

    public Object pup(){
        if (size == 0){
            throw  new EmptyStackException();
        }
        return elements[size--];
    }

    private void ensureCapacity(){
        if (elements.length == size){
            elements = Arrays.copyOf(elements,size*2+1);
        }
    }

}

這段程序并沒有明顯的錯誤,如果是棧先是增長,然后再收縮,那么,從棧中彈出來的對象將不會被當(dāng)作垃圾回收,因為里面的數(shù)組里引用著它,棧內(nèi)部維護著這些對象的過期引用,過期引用就是指永遠也不會再被解除的引用。

這類問題的修復(fù)方法很簡單:一旦對象引用已經(jīng)過期,只需清空這些應(yīng)用即可。

沒必要對于每一個對象引用,一旦程序不再用到它,就把它清空。清空對象引用應(yīng)該是一種例外,而不是一種規(guī)范行為,消除過期引用最好的辦法是讓包含該對象的變量結(jié)束其生命周期。一般而言,只要類是自己管理內(nèi)存,程序員就應(yīng)該警惕內(nèi)存泄漏問題,一旦元素被釋放掉,則該元素中包含的任何對象引用都應(yīng)該被清空。

內(nèi)存泄漏的另一個常見來源是緩存,一旦你把對象放在緩存中,他就很容易被遺忘掉,從而使得它不再有用之后很長一段時間內(nèi)仍然留在緩存中??梢杂肳eakHashMap

內(nèi)存泄漏的第三個常見來源是監(jiān)聽器和其他回掉,一般都要取消注冊,或者用弱引用

內(nèi)存泄漏通常不會表現(xiàn)成明顯的失敗,所以他們可以再一個系統(tǒng)中存在很多年,往往通過仔細檢查代碼,借助于Heap刨析工具才能發(fā)現(xiàn)內(nèi)存泄漏問題。

7 避免使用終結(jié)方法

終結(jié)方法(finalizer)通常是不可預(yù)測的,也是很危險的,一般情況下是不必要的。

C++的析構(gòu)器是回收一個對象所占用資源的常規(guī)方法,是構(gòu)造器所必須的對應(yīng)物,也可以用來回收其他的非內(nèi)存資源,而在Java中,一般用try-finally塊來完成類似的工作

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/69080.html

相關(guān)文章

  • Effective Java筆記

    摘要:構(gòu)造器的參數(shù)沒有確切地描述其返回的對象,適當(dāng)名稱的靜態(tài)工廠方法更容易使用,也易于閱讀。在文檔中,沒有像構(gòu)造器那樣明確標(biāo)識出來,因此,對于提供了靜態(tài)工廠方法而不是構(gòu)造器的類來說,要查明如何實例化一個類,有點困難。 第二章 創(chuàng)建和銷毀對象 第1條 考慮用靜態(tài)工廠方法代替構(gòu)造器 兩者創(chuàng)建對象的形式,例如:構(gòu)造器是new Boolean();靜態(tài)工廠方法是 public static Bool...

    Drummor 評論0 收藏0
  • Effective Java 第三版 全文翻譯

    摘要:本章中的大部分內(nèi)容適用于構(gòu)造函數(shù)和方法。第項其他方法優(yōu)先于序列化第項謹(jǐn)慎地實現(xiàn)接口第項考慮使用自定義的序列化形式第項保護性地編寫方法第項對于實例控制,枚舉類型優(yōu)先于第項考慮用序列化代理代替序列化實例附錄與第版中項目的對應(yīng)關(guān)系參考文獻 effective-java-third-edition 介紹 Effective Java 第三版全文翻譯,純屬個人業(yè)余翻譯,不合理的地方,望指正,感激...

    galois 評論0 收藏0
  • Effective Java 3rd.Edition 翻譯

    摘要:推薦序前言致謝第一章引言第二章創(chuàng)建和銷毀對象第項用靜態(tài)工廠方法代替構(gòu)造器第項遇到多個構(gòu)造器參數(shù)時要考慮使用構(gòu)建器第項用私有構(gòu)造器或者枚舉類型強化屬性第項通過私有構(gòu)造器強化不可實例化的能力第項優(yōu)先考慮依賴注入來引用資源第項避免創(chuàng)建不必要的對象 推薦序 前言 致謝 第一章 引言 第二章 創(chuàng)建和銷毀對象 第1項:用靜態(tài)工廠方法代替構(gòu)造器 第2項:遇到多個構(gòu)造器參數(shù)時要考慮使用構(gòu)建器 第...

    KoreyLee 評論0 收藏0
  • Effective Java創(chuàng)建銷毀對象

    摘要:一考慮用靜態(tài)工廠方法代替構(gòu)造器構(gòu)造器是創(chuàng)建一個對象實例的最基本最常用的方法。開發(fā)者在使用某個類的時候,通常會使用一個構(gòu)造器來實現(xiàn),其實也有其他方式可以實現(xiàn)的,如利用發(fā)射機制。 一、考慮用靜態(tài)工廠方法代替構(gòu)造器 構(gòu)造器是創(chuàng)建一個對象實例的最基本最常用的方法。開發(fā)者在使用某個類的時候,通常會使用new一個構(gòu)造器來實現(xiàn),其實也有其他方式可以實現(xiàn)的,如利用發(fā)射機制。這里主要說的是通過靜態(tài)類工...

    Hwg 評論0 收藏0
  • Effective Java 之個人總結(jié)

    摘要:模式下使用來設(shè)置各個參數(shù),無法僅通過檢驗構(gòu)造器參數(shù)的有效性來保證一致性,會試圖使用不一致狀態(tài)的對象。消除過期的對象引用緩存時優(yōu)先使用,這些數(shù)據(jù)結(jié)構(gòu),及時清掉沒用的項。顯示取消監(jiān)聽器和回調(diào),或進行弱引用。 創(chuàng)建和銷毀對象 1、靜態(tài)工廠方法代替構(gòu)造器 靜態(tài)工廠方法有名稱,能確切地描述正被返回的對象。 不必每次調(diào)用都創(chuàng)建一個新的對象。 可以返回原返回類型的任何子類對象。 創(chuàng)建參數(shù)化類型實例...

    maxmin 評論0 收藏0

發(fā)表評論

0條評論

tinylcy

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<