5.6 數據類型和應用

基本類型與引用類型、強引用和弱引用java

Java中數據類型可分爲兩大類:引用類型(reference)和基本類型(primitive)。

1)基本類型有8種:boolean、char、byte、short、int、long、float、double。函數

  它們都有相應的包裝類,這些包裝類都屬於引用類型,它們依次是:Boolean、Character、Byte、Short、Integer、Long、Float、Double。佈局

2)引用類型:全部Java對象都是經過對象引用(Object References)進行訪問的,相似於C++中的指針,這個引用指向堆heap中的某塊區域,實際的對象存在於heap中。例如,聲明以下代碼:編碼

int prim = 10;
Integer refer = new Integer(10);

這二者在內存中的佈局以下圖所示:spa

 

Java/Android中有四種引用類型,分別是:

1. Strong reference - 強引用

  實際編碼中最多見的一種引用類型。常見形式如:A a = new A();等。強引用自己存儲在棧內存中,其存儲指向對內存中對象的地址。通常狀況下,當對內存中的對象再也不有任何強引用指向它時,垃圾回收機器開始考慮可能要對此內存進行的垃圾回收。如當進行編碼:a = null,此時,剛剛在堆中分配地址並新建的a對象沒有其餘的任何引用,當系統進行垃圾回收時,堆內存將被垃圾回收。線程

SoftReference、WeakReference、PhantomReference都是類java.lang.ref.Reference的子類。Reference做爲抽象基類,定義了其子類對象的基本操做。Reference子類都具備以下特色:指針

  1) Reference子類不能無參化直接建立,必須至少以強引用對象爲構造參數,建立各自的子類對象;code

2) 由於1中以強引用對象爲構造參數建立對象,所以,使得本來強引用所指向的堆內存中的對象將再也不只與強引用自己直接關聯,與Reference的子類對象的引用也有必定聯繫。且此種聯繫將可能影響到對象的垃圾回收。根據不一樣的子類對象對其指示對象(強引用所指向的堆內存中的對象)的垃圾回收不一樣的影響特色,分別造成了三個子類,即SoftReference、WeakReference和PhantomReference。對象

 2. Soft Reference - 軟引用

A a = new A();
SoftReference<A> srA = new SoftReference<A>(a);

 

   經過對象的強引用爲參數,建立了一個SoftReference對象,並使棧內存中的wrA指向此對象。blog

此時,進行以下編碼:a = null,對於本來a所指向的A對象的垃圾回收有什麼影響呢?

  當 a = null後,堆內存中的A對象將再也不有任何的強引用指向它,但此時尚存在srA引用的對象指向A對象。當第一次調用srA.get()方法返回此指示對象時,因爲垃圾回收器頗有可能還沒有進行垃圾回收,此時get()是有結果的,這個很好理解。當程序執行System.gc();強制垃圾回收後,經過srA.get(),發現依然能夠獲得所指示的A對象,說明A對象並未被垃圾回收。

那麼,軟引用所指示的對象何時纔開始被垃圾回收呢?須要知足以下兩個條件:

  1.當其指示的對象沒有任何強引用對象指向它;    

  2.當虛擬機內存不足時。

所以,軟引用變相的延長了其指示對象佔據堆內存的時間,直到虛擬機內存不足時垃圾回收器纔回收此堆內存空間。

 3. Weak Reference - 弱引用

一樣的,弱引用的通常使用形式以下:

A a = new A();
WeakReference<A> wrA = new WeakReference<A>(a);

 

當沒有任何強引用指向此對象時,其垃圾回收又具備什麼特性呢?

  當 a = null 後,堆內存中的A對象將再也不有任何的強引用指向它,但此時尚存在wrA引用的對象指向A對象。當第一次調用srA.get()方法返回此指示對象時,因爲垃圾回收器頗有可能還沒有進行垃圾回收,此時get()是有結果的;當進行垃圾回收後,wrA.get()將返回null,代表其指示對象進入到了垃圾回收過程當中。所以,對弱引用特色總結爲:

  WeakReference不改變原有強引用對象的垃圾回收時機,一旦其指示對象沒有任何強引用對象時,此對象即進入正常的垃圾回收流程

  那麼,依據此特色,極可能有疑問:WeakReference存在又有什麼意義呢?

  其主要使用場景見於:當前已有強引用指向強引用對象,此時因爲業務須要,須要增長對此對象的引用,同時又不但願改變此引用的垃圾回收時機,此時WeakReference正好符合需求,常見於一些與生命週期的場景中。

例如:結合靜態內部類和WeakReference來解決Activity中可能存在的Handler內存泄露問題。

  定義Handler時常會收到一個警告信息:This Handler class should be static or leaks might occur ...

  大體的意思是建議將Handler定義成內部靜態類,並在此靜態內部類中定義一個WeakReference的引用,因爲指示外部的Activity對象。

  問題分析:Activity具備自身的生命週期,Activity中新開啓的線程運行過程當中,可能此時用戶按下了Back鍵,或系統內存不足等但願回收此Activity,因爲Activity中新起的線程並不會遵循Activity自己的什麼週期,也就是說,當Activity執行了onDestroy,因爲線程以及Handler 的HandleMessage的存在,使得系統本但願進行此Activity內存回收不能實現,由於非靜態內部類中隱性的持有對外部類的引用,致使可能存在的內存泄露問題。

  所以,在Activity中使用Handler時,一方面須要將其定義爲靜態內部類形式,這樣可使其與外部類(Activity)解耦,再也不持有外部類的引用,同時因爲Handler中的handlerMessage通常都會多少須要訪問或修改Activity的屬性,此時,須要在Handler內部定義指向此Activity的WeakReference,使其不會影響到Activity的內存回收同時,能夠在正常狀況下訪問到Activity的屬性。

4.PhantomReference

  對於SoftReference和WeakReference,還有一個構造器參數爲ReferenceQueue<T>,當SoftReference或WeakReference所指示的對象確實被垃圾回收後,其引用將被放置於ReferenceQueue中。注意上文中,當SoftReference或WeakReference的get()方法返回null時,僅是代表其指示的對象已經進入垃圾回收流程,此時對象不必定已經被垃圾回收。而只有確認被垃圾回收後,若是ReferenceQueue,其引用纔會被放置於ReferenceQueue中。

與SoftReference或WeakReference相比,PhantomReference主要差異體如今以下幾點:

  • PhantomReference只有一個構造函數PhantomReference(T referent, ReferenceQueue<? super T> q),所以,PhantomReference使用必須結合ReferenceQueue
  • 無論有無強引用指向PhantomReference的指示對象,PhantomReference的get()方法返回結果都是null。

  虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列(ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,若是發現它還有虛引用,就會在回收對象的內存以前,把這個虛引用加入到與之關聯的引用隊列中。

相關文章
相關標籤/搜索