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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Effective Java:创建和销毁对象

發布時間:2025/3/20 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Effective Java:创建和销毁对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:

? 讀這本書第1條規則的時候就感覺到這是一本很好的書,可以把我們的Java功底提升一個檔次,我還是比較推薦的。本博客是針對《Effective Java》這本書第2章所寫的一篇讀書筆記。博客中也有會一些個人對某個模塊的理解和深入探究,希望與大家一起進步。


概述:

? 本章的主題是創建和銷毀對象:何時以及如何創建對象,何時以及如何避免創建對象,如何確保它們能夠適時地銷毀,以及如何管理對象銷毀之前必須進行的各種清理動作。


相關內容:

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

思路解析:

? 如果有人問你,如何去初始化一個類的對象實例時,你的第一反應可能就是去實現類的構造器。那如果我告訴你,這樣的做法,其實并不是最好的方法,你可能會感覺意想不到,不會啊,老師和書上都是這樣寫的啊!怎么可能不去實現類的構造器就可以初始化一個類的對象實例呢?

? 辦法還真有!如果你學習過一些設計模式(這里是廢話了,如果你學習過設計模式,那你肯定早就知道是怎么回事了),比如單件模式。單件模式會涉及到一個這樣的問題:如何讓我們類的對象實現只被初始化一次呢?你可以使用類的構造器小小地實踐一下,不管是打日志還是Debug,我想答案是一樣的,不可能完成!這時,你就需要了解和學習用靜態工廠方法來代替構造器了,你可以模仿以下實現。

public static ClassA getInstance() {return new ClassA; } ? 看到以上代碼,可能你會有所抱怨,不對啊,上面的方法沒有達成我們需求中的效果啊,你一定是在耍我!


? 先不要著急,上面的方法的確只是一個思路過程,如果你想讓你的對象只對被實例化一次,你可以模仿以下代碼:

public static ClassA getInstance() {if(mInstance == null) {mInstance = new ClassA();}return mInstance; } ? 我想實現了以上代碼的你可能會很開心,這樣的確可以只實例化一個對象了。如果你的好奇心足夠強大的話,我想你還應該嘗試一下,使用構造器來重新實例一次或N次。還是可以實例化很多個對象實例,對不對?別擔心,我沒有騙你,是要利用以上的靜態工廠方法,不過你還有一件小事沒有去完成,那就是屏蔽默認的構造方法。像下面這樣的:

private ClassA() {// do something!!! } ? 沒錯,就是這樣,你可以在私有的構造器中添加一些你想添加的,這都沒有關系,但是請保證它的私有性。 可能看到這里,你沒有明白一個靜態的工廠方法會給我們帶來什么樣的好處。下面就是對靜態工廠方法的優點介紹。


靜態工廠方法的優點:

? a.它們有名稱:你可以使用對方法的合理命名來提示用戶,這一次被創建出來的是什么樣的對象。

? b.不必在每次調用它們的時候都創建一個新的對象:這一點上面的單件模式也有提到,這一優點的優勢在于單件模式本身實在的需求和節約資源開支。

? c.可以返回任何子類型的對象:這種靈活性的一種應用是,API可以返回對象,同時又不會使對象的類變成公有的。以這種方式隱藏實現類會使API變得非常簡潔。

? d.輕松創建相同參數的不同對象:想像一下,如果我們想要創建兩個不同的對象,而這兩個對象在創建的過程中都接受一個int型的參數,請問要如何創建?靜態工廠方法就是答案!


靜態工廠方法的缺點:

? a.類如果不含有僅有的或是受保護的構造器,就不能被子類化:這里你可能會困惑,為什么這樣會構成一個缺點?仔細一想,你肯定會原來如此。

? b.它們與其他的靜態方法實際上沒有任何區別。


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

? 對于這一點我還是保留對大家的信任,大家都已經熟練掌握了它的使用和好處。它會使用在這樣一個必要的環境下:如果你想構造一個類的對象實例,而這個類在構造器上需要傳遞很多參數,這里我們假設有10個。是不是想想就覺得很可怕,它充斥著我們的大腦,并抗爭著說這樣很麻煩,我們不要這樣來做吧。而看起來麻煩還是小事,只要你耐心一點,總能渡過,不過如果你要把兩個或N個參數給弄混了,那我想后果一定很“精彩”。

? 在這種情境下,我們可以考慮一下使用構建器。別被構建器的名稱給嚇到了,如果我換一個說法,相信你就會明白了。那就是把合適的參數封裝成一個類,在類中使用setter和getter來實現需求。

? 這樣的做法不僅可以讓代碼更簡潔,還不容易讓參數混淆,真是一個好東西啊。


3.用私有構造器或者枚舉類型強化Singleton屬性

? 在第1條中我們說到了關于單件模式的一些使用場景,下面會有一些額外介紹。如果你對單件模式還有一些想要了解的,可以在Java設計模式中進行了解。

? 對于如何使用私有構造器優化Singleton屬性我們在第1條和Java設計模式的《Java設計模式——單件模式》中都有介紹,這里不再贅述。

? 關于如何使用枚舉來強化Singleton屬性,我們可以像下面這樣:

public enum Elvis {INSTANCE;public void leaveTheBuilding(){...} } 這種方法和公有域方法相近,但是它更加簡潔,無償地提供了序列化機制,絕對防止多次實例化。雖然這種方法還沒有廣泛采用,但是單元素的枚舉類型已經成為實現Singleton的最佳方法


4.避免創建不必要的對象

? 從節省資源的角度考慮,我們應該盡量避免創建不必要的對象。看到這里,你可能會說上面提到的單件模式算不算這個避免創建不必要的對象呢?我說它是,又不全是。因為它不單是因為要避免創建不必要的對象而設計的,更多的是它要實現的是只能有一個對象。

? 你是否會像這樣來創建一個字符串:

String s = new String("abcdefghi");

? 可能你會說你沒有,可是你可能很少會想到這樣的一種方式來初始化一個字符串對象的實例。但是我想要說的是最好不要像上面那樣創建,因為它在一個多次創建中會產生很多不必要的實例。

? 你可以這樣來改進它,使之更加合理:

String s = "abcdefghi"; ? 在Java的機制中,上面的這個版本只用了一個String實例,對于所有在同一臺虛擬機中運行的代碼,只要它們包含的字符串字面常量,該對象就會被重用。


5.消除過期的對象引用

? 在項目優化的時候,我們經常可能要去做內存泄漏的檢測。不要以為Java已經有了垃圾回收的機制,我們就可以坐享其成,不再去考慮內存管理的事情了。如果你想了解更多內容,可以去看《Android開發中,可能會導致內存泄漏的問題》這篇文章。

? 下面請看這個例子:Can you spot the "memory leak"?

public class Stack {private Object[] elements;private int size = 0;private static final int DEFAULT_INITIAL_CAPACITY = 16;public Stack() {elements = new Object[DEFAULT_INITIAL_CAPACITY];}public void push(Object e) {ensureCapacity();elements[size++] = e;}public Object pop() {if (size == 0) {throw new EmptyStackException();}return elements[--size];}private void ensureCapacity() {if(elements.length == size) {elements = Arrays.copyOf(elements, 2 * size + 1);}} }
? 你能看出這段代碼的問題所在嗎?

? 我們試想一下,如果我們的棧在先增加元素,然后再收縮。那么,這時從棧中pop的對象不會被當作垃圾回收,即使用棧的程序不再引用它們,它們也不會被回收。這是因為,棧內部維護著這些對象的過期引用。這么說,可能你還不清楚什么是過期引用。換句話說吧,就是說我們的棧還在,這些被pop的對象曾經是屬于這個棧的,它們都還持有這個活動棧的引用,那么Java的垃圾回收機制就不會對它們怎么樣了。

? 這個就有一點像Android中,初始化了很多持有生命周期較長的Context的對象,而這些對象由于始終持有Context的引用,所以不會被Java回收機制回收。

? 這類問題的解決方法也很簡單:一旦對象引用已經過期,只需清空這些引用即可。根據這一點,改進的程序如下:

public Object pop() {if (size == 0) {throw new EmptyStackException();}Object result = elements[--size];elements[size] = null;return result;}? 清空過期引用的另一個好處是,如果它們以后又被錯誤地解除引用,程序就會立即拋出一個NullPointerException的異常,而不是悄悄地錯誤運行下去。

總結

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

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