上次说到了JVM的垃圾回收机制和JVM中对象的生命周期,今天给大家讲个方法,叫做析构方法finalize,我想搞过C++的人都知道,而且是内存管理技术中相当重要的一部分。但是,在Java中好像没有这个概念,这是因为,理论上JVM负责对象的析构(销毁与回收)工作,finalize是Object类中的一个方法,并且是protected,由于所有的类都继承了Object对象,因此,就都隐式的继承了改方法,不过可以重写这个方法,如果重写此方法,最后一句必须写上super.finalize()语句,因为finalize方法没有自动实现递归调用。那我们在什么时候要重写它呢?当有一些不容易控制并且非常重要的资源时,要放到finalize方法中,例如:一些I/O的操作,数据的连接等等,这些资源的释放对整个应用程序是非常关键的。
我先让大家看一段代码:
1publicclassTestA{ 2 Object obj=null; 3 publicTestA(){ 4 obj=newObject(); 5 System.out.println("创建obj对象"); 6 } 7 8 protectedvoiddestroy(){ 9 System.out.println("释放obj对象"); 10 obj=null; 11 //释放自身所占用的资源 12 } 13 14 protectedvoidfinalize()throwsjava.long.Throwable{ 15 destroy(); 16 //递归调用超类中的finalize方法 17 super.finalize(); 18 } 19} |
finalize方法最终是由JVM中的垃圾回收器调用的,由于垃圾回收器调用finalize的时间是不确定或者不及时的,调用时机对我们来说是不可控的,因此我们可以在自己的类中声明一个destory()方法,在这个方法中添加释放系统资源的处理代码,但是还是建议你将对destroy()方法的调用放入当前类的finalize()方法体中,因为这样做更保险,更安全。
我们知道类中的静态变量在程序运行期间,其内存空间对所有该类的对象实例而言是共享的,为了节省系统内存开销、共享资源,应该将一些变量声明为静态变量。通过下面的例子,你就会发现有什么不同。
代码一:
1publicclassMemoryTest { 2 staticclassData{ 3 privateintweek; 4 privateString name; 5 Data(inti, String s){ 6 week=i; 7 name=s; 8 } 9 } 10 11 Data weeks[]={ 12 newData(1,"monday"), 13 newData(2,"Tuesday"), 14 newData(3,"Wednesday"), 15 newData(4,"Thursday"), 16 newData(5,"Friday"), 17 newData(6,"Saturday"), 18 newData(7,"Sunday") 19 }; 20 21 publicstaticvoidmain(String[] args) { 22 finalintN=20000; 23 MemoryTest test=null; 24 for(inti=0; i<=N; i++) { 25 test=newMemoryTest(); 26 } 27 System.out.println(test.weeks.length); 28 } 29} |