亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

tinylcy / 787人閱讀

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

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

例:

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

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

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

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

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

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

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

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

/**
 * Created by Newtrek on 2017/10/31.
 * 服務(wù)提供者接口
 */
public interface Provider {
//    提供服務(wù)實(shí)例,用服務(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)造保護(hù)
    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實(shí)例
     */
    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í)例的時(shí)候,它們是代碼變得更加簡潔

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

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

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

 Map> m=HashMap.newInstance(); 

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

缺點(diǎn)

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

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

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

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

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

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

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

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

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

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

例如:

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

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

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

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

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

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

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

6 消除過期的對象引用

不要以為Java有垃圾回收機(jī)制,能自動(dòng)管理內(nèi)存,自動(dòng)回收垃圾,就可以不管了,其實(shí)不然。
內(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);
        }
    }

}

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

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

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

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

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

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

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

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

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

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

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

相關(guān)文章

  • Effective Java筆記

    摘要:構(gòu)造器的參數(shù)沒有確切地描述其返回的對象,適當(dāng)名稱的靜態(tài)工廠方法更容易使用,也易于閱讀。在文檔中,沒有像構(gòu)造器那樣明確標(biāo)識(shí)出來,因此,對于提供了靜態(tài)工廠方法而不是構(gòu)造器的類來說,要查明如何實(shí)例化一個(gè)類,有點(diǎn)困難。 第二章 創(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ù)和方法。第項(xiàng)其他方法優(yōu)先于序列化第項(xiàng)謹(jǐn)慎地實(shí)現(xiàn)接口第項(xiàng)考慮使用自定義的序列化形式第項(xiàng)保護(hù)性地編寫方法第項(xiàng)對于實(shí)例控制,枚舉類型優(yōu)先于第項(xiàng)考慮用序列化代理代替序列化實(shí)例附錄與第版中項(xiàng)目的對應(yīng)關(guān)系參考文獻(xiàn) effective-java-third-edition 介紹 Effective Java 第三版全文翻譯,純屬個(gè)人業(yè)余翻譯,不合理的地方,望指正,感激...

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

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

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

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

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

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

    maxmin 評論0 收藏0

發(fā)表評論

0條評論

tinylcy

|高級講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<