赛迪网 > IT技术 Java > 头条列表
  IT资讯搜索
 
IT产品搜索
[程序开发][网管世界][网络安全][数据库技术]
[操作系统][嘉宾聊天·在线访谈][活动集锦]
[精彩专题][Symantec专区][订阅IT技术周刊]
[开发论坛][网管论坛][安全论坛][数据库论坛]
[操作系统论坛][Sybase专区][IBM dW技术专区]
[病毒求助][病毒与漏洞播报][文档·源码下载]

JAVA中具有实例缓存的不可变类

发布时间:2007.12.04 04:45     来源:赛迪网    作者:执木

不可变类的实例的状态不会变化,这样的实例可以安全地被其他与之关联的对象共享,还可以安全地被多个线程共享。为了节省内存空间,优化程序的性能,应该尽可能地重用不可变类的实例,避免重复创建具有相同属性值的不可变类的实例。

在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.在程序运行过程中,需要频繁访问不可变类的一些特定实例。这些实例拥有与程序本身同样长的生命周期。

  (责任编辑:包春林)


[ 发表评论 ] 字体[  ] [ 打印 ] [ 进入博客 ] [ 进入论坛 ]  [ 推荐给朋友 ]
  相关文章
· 关于Java性能的讨论 (12-03) · 学习心得 - JSP处理异常及一些高级主题 (11-29)
· 用Javascript来评估用户输入密码的强度 (11-29) · Java程序开发过程中异常处理的特殊情况 (11-29)
· NetBeans和JBoss 结合使用的入门指南 (11-29) · 解决JSP开发Web程序中文显示三种方法 (11-29)
· 初学实用:实例讲解Java中的接口的作用 (11-29) · 实例讲解在JSP开发中的对象和范围属性 (11-29)
· 使用Java解析网络数据流的三种特殊方法 (11-29) · 简述构建高性能J2EE应用的五种核心策略 (11-29)
  客户需求反馈表
* 姓  名:
更多资料  了解方案  认识厂商
* 单位名称:
* 联系电话:
* 电子邮件:
  赛迪推荐  
  手机·资费 ·新品·导购·评测·手机资费·宽带
手机搜索  诺基亚 N73 MOTO Z6
  IT产品 ·笔记本·台式机·服务器·打印·投影
IT产品搜索 
  IT技术 ·开发·网管·安全·数据库·操作系统
  信息化 ·热点·专题·访谈·周刊·方案案例
· 电子商务行业规范出台 电子商务发展目标与规划
· 中小企业网站存在盲目性 消费习惯需重点培养
· 天灾中信息化显力量 CIO如何应对新领导IT改革
· 河南网通数据中心工程 网御神州VPN解决方案
  IT博客 ·曾剑秋·项立刚·Java学习·网管
  IT技术论坛 ·开发·网管·安全·数据库·系统