Java对象的生命周期与作用域的讨论(转)

导读:
  Java对象的生命周期大致包括三个阶段:对象的创建,对象的使用,对象的清除。因此,对象的生命周期长度可用如下的表达式表示:T = T1 + T2 +T3。其中T1表示对象的创建时间,T2表示对象的使用时间,而T3则表示其清除时间。由此,我们可以看出,只有T2是真正有效的时间,而T1、T3则是对象本身的开销。下面再看看T1、T3在对象的整个生命周期中所占的比例。
  我们知道,Java对象是通过构造函数来创建的,在这一过程中,该构造函数链中的所有构造函数也都会被自动调用。另外,默认情况下,调用类的构造函数时,Java会把变量初始化成确定的值:所有的对象被设置成null,整数变量(byte、short、int、long)设置成0,float和double变量设置成0.0,逻辑值设置成false。所以用new关键字来新建一个对象的时间开销是很大的,如表1所示。
  表1 一些操作所耗费时间的对照表
  运算操作 示例 标准化时间
  本地赋值 i = n 1.0
  实例赋值 this.i = n 1.2
  方法调用 Funct() 5.9
  新建对象 New Object() 980
  新建数组 New int[10] 3100
  从表1可以看出,新建一个对象需要980个单位的时间,是本地赋值时间的980倍,是方法调用时间的166倍,而若新建一个数组所花费的时间就更多了。
  再看清除对象的过程。我们知道,Java语言的一个优势,就是Java程序员勿需再像C/C++程序员那样,显式地释放对象,而由称为垃圾收集器(Garbage Collector)的自动内存管理系统,定时或在内存凸现出不足时,自动回收垃圾对象所占的内存。凡事有利总也有弊,这虽然为Java程序设计者提供了极大的方便,但同时它也带来了较大的性能开销。这种开销包括两方面,首先是对象管理开销,GC为了能够正确释放对象,它必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等。其次,在GC开始回收“垃圾”对象时,系统会暂停应用程序的执行,而独自占用CPU。
  因此,如果要改善应用程序的性能,一方面应尽量减少创建新对象的次数;同时,还应尽量减少T1、T3的时间,而这些均可以通过对象池技术来实现。
  对象池技术的基本原理
  对象池技术基本原理的核心有两点:缓存和共享,即对于那些被频繁使用的对象,在使用完后,不立即将它们释放,而是将它们缓存起来,以供后续的应用程序重复使用,从而减少创建对象和释放对象的次数,进而改善应用程序的性能。事实上,由于对象池技术将对象限制在一定的数量,也有效地减少了应用程序内存上的开销。
  实现一个对象池,一般会涉及到如下的类:
  1)对象池工厂(ObjectPoolFactory)类
  该类主要用于管理相同类型和设置的对象池(ObjectPool),它一般包含如下两个方法:
  createPool:用于创建特定类型和设置的对象池;
  destroyPool:用于释放指定的对象池;
  同时为保证ObjectPoolFactory的单一实例,可以采用Singleton设计模式,见下述getInstance方法的实现:
  public static ObjectPoolFactory getInstance() { if (poolFactory == null) {  poolFactory = new ObjectPoolFactory(); } return poolFactory;
  }
  2)参数对象(ParameterObject)类
  该类主要用于封装所创建对象池的一些属性参数,如池中可存放对象的数目的最大值(maxCount)、最小值(minCount)等。
  3)对象池(ObjectPool)类
  用于管理要被池化对象的借出和归还,并通知PoolableObjectFactory完成相应的工作。它一般包含如下两个方法:
  getObject:用于从池中借出对象;
  returnObject:将池化对象返回到池中,并通知所有处于等待状态的线程;
  4)池化对象工厂(PoolableObjectFactory)类
  该类主要负责管理池化对象的生命周期,就简单来说,一般包括对象的创建及销毁。该类同ObjectPoolFactory一样,也可将其实现为单实例。
  
  
  
  Java对象的作用域
  作用域与生命周期的区别:
  作用域是对象起作用的地方,生命周期对象生存的时段,就JAVA来说,对象不被引用了也就OVER了。即生命周期定义的是时间,作用域定义的是空间。
  
  变量的生命周期和作用域
  Java允许在任何块中声明变量,(块:由‘{‘ 开始由‘}’ 结束) 。
  一个”块”定义一个作用域.作用域决定了哪些变量对程序的其他部分是可视的,同时还确定了这些对象的生命周期.
  定义作用域由一个方法和它的左’{‘开始,如果方法带有参数,那么它们也在方法的作用域之内。
  一般规则是:在一个作用域内声明的变量对外部的作用域定义的程序不可视(不可访问),因此,在一个作用域中声明变量时,就是在使变量本地化并受其保护而拒绝未经授权的
  访问和修改.其实,作用域规则为变量提供了封装的功能. 作用域可以嵌套,每次创建一个新的,嵌套的作用域,外部作用域就封入到内部作用域,这就意味着外部作用域声明的对象在内部作用域中的代码是可以访问的,反之则是不正确的。
  变量的作用域影响了其生命周期。进入到变量的作用域创建变量,离开变量的作用域则清除变量。也就是说变量离开了它的作用域则不再保存它的值.
  因此变量的生命周期受其作用域限制。
  
  Java对象的作用域
  作用域public,private,protected,以及不写时的区别
  答:区别如下:
  作用域 当前类 同一 package 子孙类 其他 package
  public √ √ √ √
  protected √ √ √ ×
  friendly √ √ × ×
  private √ × × ×
  不写时默认为friendly
  
  JavaBean作用域
  在Web应用中,JavaBean存储许多不同的属性集合中。每一个不同的属性集合都有不同的生命周期规则。该规则定义了生命周期和可见性我们称之为作用域(Scope),JSP定义的作用域如下:
  1.page Bean在当前请求的单个JSP页面可见(相当于Servlet的service方法中的局部
  变量)
  2.Request Bean不仅在单个页面可见,也可以在被页面包含(include)的页面或servlet
  中可见,或者转向(Forward)的页面可见。
  3.Session Bean在特殊用户session的所有JSP或Servlet中可见。
  4.Application Bean在WEB 应用中的所有JSP,或Servelt中可见。
  必须记住的是JSP和Servlet在同一个WEB应用中共享同一组Bean。例如一个Bean在Servlet中存在request的属性中:
  MyCart mycart = new MyCart(...);
  request.setAttribute("cart", mycart);

时间: 2024-10-28 23:40:34

Java对象的生命周期与作用域的讨论(转)的相关文章

Java线程的生命周期(转)

  Java线程的生命周期   一个线程的产生是从我们调用了start方法开始进入Runnable状态,即可以被调度运行状态,并没有真正开始运行,调度器可以将CPU分配给它,使线程进入Running状态,真正运行其中的程序代码.线程在运行过程中,有以下几个可能的去向: (1)调度器在某个线程的执行过程中将CPU分配给了其它线程,则这个线程又变为Runnable状态,等待被调度. (2)调度器将CPU分配给了该线程,执行过程中没有遇到任何阻隔,运行完成直接结束,也就是run()方法执行完毕. (3

第四章 Hibernate中的持久化对象的生命周期

4.1提供对象状态管理的目的      使开发者不再需要理会底层数据库系统的细节      使用Hibernate的开发者应该总是关注对象的状态(state),不必考虑SQL语句的执行 4.2 Hibernate 仅仅定义了三种状态:瞬时(临时).持久和脱管(游离),对客户端代码隐藏了其内部实现的复杂性 4.2.1 瞬时对象(Transient Object):Hibernate中的持久化对象的生命周期         使用new操作符初始化的对象不是立刻就持久的.它们的状态是瞬时的,也就是说它

我所理解的Remoting (2) :远程对象的生命周期管理[下篇]

在上一篇文章中([原创]我所理解的Remoting(2):远程对象生命周期的管理-Part I),我简要的讲述了CLR的垃圾回收机制和Remoting 基于Lease的对象生命周期的管理.在这篇文章中,我们将以此为基础,继续我们的话题.在文章的开始,我将以我的理解详细地讲述Remoting中两个重要的概念--Lease和Sponsorship.然后我通过一个Sample,为大家演示如何以不同的方法延长远程对象的生命周期. 我们先不谈远程对象.本地对象. 不管是远程的对象,还是本地对象,都对于程序

c++-C++函数返回的临时匿名对象的生命周期

问题描述 C++函数返回的临时匿名对象的生命周期 C++函数返回的临时匿名对象什么时候被释放内存 #include using namespace std; class A { public: int x; A(int a){cout<<"creating"<<endl;x=a;} A(const A& a){cout<<"copy"<<endl;x=a.x;} void operator=(A& a)

Java 线程的生命周期详细介绍及实例代码_java

当线程被创建并启动之后,它既不是一启动就进入执行状态,也不是一直处于执行状态,在其生命周期中,要经过"新建(New)"."就绪(Runnable)"."运行(Running')"."阻塞(Blocked)"和"死亡(Dead)"五种状态.线程在创建之后,不可能一直霸占着CPU独立运行,需要在多个线程之间切换,所以大部分时间处于运行.阻塞之间切换.  一.线程的状态 线程的存在有几种不同的状态,如下: New

C++临时性对象的生命周期详细解析_C 语言

有关临时对象的生命周期有三种情况: 1)一般情况:临时性对象的被摧毁,应该是对完整表达式(full-expression)求值过程中的最后一个步骤.该完整表达式造成临时对象的产生. 实例代码如下: 复制代码 代码如下: #include <iostream>using namespace std;class A{public:    A(int i): m_i(i)    {        cout << "A(): " << m_i <<

java线程的生命周期

1.线程的生命周期 线程是一个动态执行的过程,它也有一个从产生到死亡的过程.每个Java程序至少包含一个线程:主线程. (1)线程生命周期的五种状态 1.创建(当用new 创建完一个线程对象后,该线程处于新建状态) 2.就绪(当线程对象调用了start()后,该线程处于就绪状态) 3.执行(如果处于就绪状态的线程获得CPU时间片,开始执行run方法的线程执行体,该线程处于运行状态) 4.阻塞(如果线程调用了sleep().join()或者调用了一个阻塞式IO方法等,该线程处于阻塞状态) 5.死亡

EntityFramework之领域驱动设计实践(七):模型对象的生命周期

上文中已经提到了管理领域模型对象生命周期的两大角色,即工厂与仓储,并对工厂的EntityFramework实践作了详细的描述.本节主要介绍仓储的概念,由于仓储的内容比较多,我将在接下来的两节中具体讲解仓储的架构设计与实践经验. 仓储(Repository),顾名思义,就是一个仓库,这个仓库保存着领域模型的实体对象.在业务处理的过程中,我们有可能需要把正在参与处理过程的对象保存到仓储中,也有可能会从仓储中读取需要的实体对象,抑或将对象直接从仓储中删除.上文也用一张简要的状态图描述了仓储在管理领域模

EntityFramework之领域驱动设计实践(六):模型对象的生命周期

首先应该认识到,是对象就有生命周期.这一点无论在面向对象语言还是在领域驱动设计中都适用.在领域驱动设计中,模型对象生命周期可以简要地用下图表示: 通过上图可以看到,对象通过工厂从无到有创建,创建后处于活动状态,此时可以参与领域层的业务处理:对象通过仓储实现持久化(也就是我们常说的"保存")和重建(也就是我们常说的"读取").内存中的对象通过析构而消亡,处于持久化状态的对象则通过仓储进行撤销(也就是我们常说的"删除").整个状态转换过程非常清晰.