日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

创建和销毁对象

發布時間:2023/12/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 创建和销毁对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

考慮使用靜態工廠方法代替構造器

類可以提供一個公有的靜態工廠方法(public static factory method)來返回一個類的實例。
例如,Boolean類的valueOf()方法:

public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }

提供public靜態工廠方法而不是public的構造器的優勢如下:

  • 靜態工廠方法有名稱,不過要慎重地選擇名稱
    例如,構造器BigIntger(int, int, Random)返回的BigInteger可能為素數,如果用名為BigInteger.probablePrime()的靜態工廠方法顯然更清晰。?
    示例:?BigIntegerTest

  • 不必在每次調用靜態工廠方法的時候都創建一個新對象?
    如果程序經常經常請求創建相同的對象,并且創建對象的代碼很高,則這項技術可以極大地提升性能。?
    示例:BooleanTest?
    當且僅當a==b的時候才有a.equals(b)為true, 如果類保證了這一點, 它的客戶端就可以使用==操作符來代替equals(Object)方法,這樣可以提升性能。

  • 靜態工廠方法可以返回子類類型的對象?
    API返回的對象對應的子類可以不是公有的,這種方式可以隱藏具體的實現類。?
    這項技術適合于基于接口的框架,接口為靜態工廠提供了自然返回類型。?
    接口不能有靜態方法,因此按照慣例,返回接口的靜態工廠方法是放在一個不可實例化(non-instantiability)的類中。?
    示例:?InterfaceCannotStaticTest?

    示例: java.util.Collections是一個不可實例化的類,它提供了不可修改的集合、同步集合的靜態工廠方法。我們模仿其寫了一個簡單例子:?MyListTest?

    通過使用這種靜態工廠方法,甚至要求客戶端通過接口來引用被返回的對象,而不是通過它的實現類來引用被返回的對象,這是一種良好的習慣。 為了提升軟件的可維護性和性能,返回對象的(子)類也可能隨著發行版本的不同而不同。?

    示例:EnumSetTest?發行版本1.5中引入java.util.EnumSet沒有公有的構造器,只有靜態工廠方法,返回兩種實現類之一,具體則取決于底層枚舉類型的大小。

    示例:服務提供者框架

  • 靜態工廠方法在創建參數化類型實例的時候,使得代碼更加簡潔?
    例如,創建一個Map<String, List<String>>對象,在調用參數化類的構造器時,即使類型參數明顯,也必須指明。這通常要求你連接兩次提供類型參數:
    Map<String, List<String>> map = new HashMap<String, List<String>>();?
    隨著類型參數變得越來越長,越來越復雜,這一冗長的說明也很快變得痛苦起來。?
    但是有了靜態方法,編譯器可以替你找到類型參數,這被稱作類型推導(type inference):?
    Map<String, List<String>> map = HashMap.newInstance();?
    假設HashMap提供了這個靜態工廠方法:
    public static <K, V> HashMap<K, V> newInstance() { return new HashMap<K, V>(); }?
    總有一天,Java將能夠在構造器調用以及方法調用中執行這些類型推導,但到發行版本1.6為止暫時還無法這么做。?
    遺憾的是,到發行版本1.6為止,標準的集合實現如HashMap并沒有工廠方法,但是可以把這些方法放在你自己的工具類中。

  • 公有的靜態工廠方法的缺點:

  • 類如果不含有公有的或者受保護的構造器,靜態工廠方法返回的實例不能被子類化。
  • 同樣地,對于非公有類(nonpublic classes),靜態工廠方法返回的實例也不能被子類化。 示例: MyListTest
  • 靜態工廠方法與其它的靜態方法無法被明確區分,不像構造器那樣在api文檔中被明確的標識出來。 所以,在類或接口注釋中關注靜態工廠,使用一些約定俗成的命名
  • 慣用名稱說明
    valueOfReturns an instance that has, loosely speaking, the same value as its parameters. Such static factories are effectively type-conversion methods.
    ofA concise alternative to valueOf , popularized by EnumSet.
    getInstanceReturns an instance that is described by the parameters but cannot be said to have the same value. In the case of a singleton, getInstance takes no parameters and returns the sole instance.
    newInstanceLike getInstance , except that newInstance guarantees that each instance returned is distinct from all others.
    getTypeLike getInstance , but used when the factory method is in a different class. Type indicates the type of object returned by the factory method.
    newTypeLike newInstance , but used when the factory method is in a different class. Type indicates the type of object returned by the factory method.

    簡而言之,靜態工廠方法和公有構造器都各有用處。 靜態工廠方法通常更加適合,因此切忌第一反應是提供公有的構造器,而不先考慮靜態工廠方法。

    遇到多個構造器參數時要考慮用構建器

    靜態工廠和構造器有一個共同的局限性:它們都不能很好地擴展到大量的可選參數。考慮用一個類表示一個食品的營養成分表。對于這樣的類,應該用哪個構造器或者靜態方法來編寫呢?

  • 重疊構造器(telescoping constructor)?
    示例: telescoping_constructor/NutritionFacts?
    ① 當有許多參數的時候,客戶端代碼會很難編寫,并且仍然較難以閱讀。?
    ② 如果讀者想知道那些值是什么意思,必須很仔細地數著這些參數來探個究竟。如果客戶端不小心顛倒了其中兩個參數的順序,編譯器也不會出錯,但是在程序運行時會出現錯誤行為。
  • JavaBeans模式:調用一個無參構造器來創建對象,然后調用setter()方法來設置每個必要的參數,以及每個相關的可選參數。
    示例: javabeans/NutritionFacts?
    ① 無法保證一致性:JavaBean模式自身有著很嚴重的缺點,因為構造過程被分到了幾個調用中,在構造過程中JavaBean可能處在不一致的狀態。類無法僅僅通過檢驗構造器參數的有效性來保證一致性。試圖使用處于不一致狀態的對象,將會導致失敗,這種失敗調試起來十分困難。?
    ② 阻止了把類做成不可變,這就需要程序員付出額外的努力來確保它的線程安全。
  • Builder模式?
    示例:builder/NutritionFacts?
    這樣的客戶端代碼很容易編寫,而且易讀。Builder模式模擬了具名的可選參數,就像Python一樣。?
    對參數加強約束條件: build()方法檢驗或者多個setter()方法檢驗這些約束條件,如果該約束條件沒有得到滿足,就拋出IllegalStateException或IllegalArgumentException。?
    設置了參數的Builder生成了一個很好的抽象工廠(Abstract Factory)。Java中的Class對象就是一個抽象工廠,用newInstance()方法充當build()方法的一部分。?
    Builder模式也有它自身不足,為了創建對象,必須先創建它的構建器,它還會比重疊構造器模式更加冗長,因此只有在很多參數(4個以上)的時候才考慮使用Builder模式。但是要記住,將來你可能需要添加參數,如果一開始就使用構造器或者靜態工廠,等到類需要多個參數時才添加構建器,就無法控制,那些過時的構造器或者靜態工廠顯得十分不協調。因此通常最好一開始就使用構建器。
  • 用私有構造器或者枚舉類型強化Singleton屬性

    Singleton指僅僅被實例化一次的類。Singleton通常被用來代表那些本質上唯一的系統組件。?
    在Java 1.5發行版本之前,實現Singleton有兩種方法。這兩種方法都要把構造器保持為私有的,并導出公有的靜態成員,以便允許客戶端能夠訪問該類的唯一實例。?
    第一種方法,公有靜態成員是一個final域。示例: field/Elvis.java?
    私有構造器僅被調用一次,用來實例化公有的靜態域Elvis.INSTANCE。?
    但要提醒一點:享有特權的客戶端可以借助AccessibleObject.setAccessible()方法,通過反射機制調用私有構造器,示例:ModifyingSingleton?。如果需要抵御這種攻擊,可以修改構造器,讓它在被要求創建第二個實例的時候拋出異常。

    通過私有構造器強化不可實例化的能力

    避免創建不必要的對象

    消除過期的對象引用

    避免使用終結方法

    參考資料

    • 《Effective Java》第2版
    • Java反射AccessibleObject類的setAccessible方法

    轉載于:https://www.cnblogs.com/fireway/p/7266588.html

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的创建和销毁对象的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。