程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> JAVA中具有實例緩存的不可變類

JAVA中具有實例緩存的不可變類

編輯:關於JAVA

不可變類的實例的狀態不會變化,這樣的實例可以安全地被其他與之關聯的對象共享,還可以安全地被多個線程共享。為了節省內存空間,優化程序的性能,應該盡可能地重用不可變類的實例,避免重復創建具有相同屬性值的不可變類的實例。

在JDK 1.5的基本類庫中,對一些不可變類,如Integer類做了優化,它具有一個實例緩存,用來存放程序中經常使用的Integer實例。JDK 1.5的Integer類新增了一個參數,為int類型的靜態工廠方法valueOf(int i),它的處理流程如下:

if(在實例緩存中存在取值為i的實例)
   直接返回這個實例
else{
  用new語句創建一個取值為i的Integer實例
  把這個實例存放在實例緩存中
  返回這個實例
}

在以下程序代碼中,分別用new語句和Integer類的valueOf(int i)方法來獲得Integer實例。

Integer a=new Integer(10);
Integer b=new Integer(10);

Integer c=Integer.valueOf(10);
Integer d= Integer.valueOf(10);

System.out.println(a==b); //打印false
System.out.println(a==c); //打印false

System.out.println(c==d); //打印true


       以上代碼共創建了3個Integer對象,每個new語句都會創建一個新的Integer對象。而Integer.valueOf(10)方法僅在第一次被調用時,創建取值為10的Integer對象,在第二次被調用時,直接從實例緩存中獲得它。由此可見,在程序中用valueOf()靜態工廠方法獲得Integer對象,可以提高Integer對象的可重用性。

     到底如何實現實例的緩存呢?緩存並沒有固定的實現方式,完善的緩存實現不僅要考慮何時把實例加入緩存,還要考慮何時把不再使用的實例從緩存中及時清除,以保證有效合理地利用內存空間。一種簡單的實現是直接用Java集合來作為實例緩存。

     下面的例程,它擁有實例緩存和相應的靜態工廠方法valueOf()。Name類的實例緩存中可能會加入大量Name對象,為了防止耗盡內存,在實例緩存中存放的是Name對象的軟引用(SoftReference)。如果一個對象僅僅持有軟引用,Java虛擬機會在內存不足的情況下回收它的內存。

例程11-12 Name.Java

import Java.util.Set;
import Java.util.HashSet;
import Java.util.Iterator;
import Java.lang.ref.*;

public class Name {

//實例緩存,存放Name對象的軟引用

private static final Set>   names=new HashSet>();

public static Name valueOf(String firstname, String lastname){ //靜態工廠方法

 Iterator> it=names.iterator();

 while(it.hasNext()){
  SoftReference  ref=it.next();//獲得軟引用
  Name name=ref.get();//獲得軟引用所引用的Name對象
 if(name!=null&& name.firstname.equals(firstname)&& name.lastname.equals(lastname))
   return name;
 }

 //如果在緩存中不存在Name對象,就創建該對象,並把它的軟引用加入到實例緩存

 Name name=new Name(firstname,lastname);
 names.add(new SoftReference(name));
 return name;

}

public static void main(String args[]){

  Name n1=Name.valueOf("小紅","王");
  Name n2=Name.valueOf("小紅","王");
  Name n3=Name.valueOf("小東","張");
  System.out.println(n1);
  System.out.println(n2);
  System.out.println(n3);
   System.out.println(n1==n2); //打印true
 }

 }

在程序中,既可以通過new語句創建Name實例,也可以通過valueOf()方法創建Name實例。在程序的生命周期中,對於程序不需要經常訪問的Name實例,應該使用new語句創建它,使它能及時結束生命周期;對於程序需要經常訪問的Name實例,那就用valueOf()方法來獲得它,因為該方法能把Name實例放到緩存中,使它可以被重用。

Tips

      從例程11-12的Name類也可以看出,在有些情況下,一個類可以同時提供public的構造方法和靜態工廠方法。用戶可以根據實際需要,靈活地決定到底以何種方式獲得類的實例。

    另外要注意的是,沒有必要為所有的不可變類提供實例緩存。隨意創建大量實例緩存,反而會浪費內存空間,降低程序的運行性能。通常,只有滿足以下條件的不可變類才需要實例緩存。

1. 不可變類的實例的數量有限。
2.在程序運行過程中,需要頻繁訪問不可變類的一些特定實例。這些實例擁有與程序本身同樣長的生命周期。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved