程序员都了解初始化的重要性,但常常会忘记同样重要的清除工作。毕竟,谁需要清除一个
int 呢?但在使用程序库时,把一个对象用完后就“弃之不顾”的做法并非总是安全的。当
然,Java 有垃圾回收器来回收无用对象占据的内存资源。但也有特殊情况:假定你的对象(并
非使用 new)获得了一块“特殊”的内存区域,由于垃圾回收器只知道释放那些经由 new
分配的内存,所以它不知道该如何释放该对象的这块 “特殊”内存。为了应对这种情况,
Java 允许你在类中定义一个名为 finalize( )的方法。它的工作原理“应该”是这样的:一旦
垃圾回收器准备好释放对象占用的存储空间,将首先调用其 finalize( )方法,并且在下一次
垃圾回收动作发生时,才会真正回收对象占用的内存。所以要是你打算用 finalize( ),就能
在“垃圾回收时刻”做一些重要的清除工作。
这里有一个潜在的编程陷阱,因为有些程序员(特别是 C++程序员)刚开始可能会误把
finalize( )当作 C++中的“析构函数”(C++中销毁对象必须用到这个函数)。所以有必要明确
区分一下:在 C++中,对象一定会被“销毁”(如果程序中没有错误的话);而 Java 里的对
象却并非总是被“垃圾回收”的。或者换句话说:
1. 对象可能不被回收。
2. 垃圾回收并不等于“析构”。
牢记这些,你就能远离困扰。这意味着在你不再需要某个对象之前,如果必须执行某些动作,
那么你得自己去做。Java 并未提供“析构函数”或相似的概念,要做类似的清除工作,你必
须自己动手创建一个执行清除工作的普通方法。例如,假设某个对象在创建过程中,会将自
己绘制到屏幕上。要是你不明确地从屏幕上将其擦除,它可能永远得不到清除。如果在
finalize( )里加入某种擦除功能,当“垃圾回收”发生时(不能保证一定会发生),finalize( )
得到了调用,图像就会被擦除。要是“垃圾回收”没有发生,图像就会一直保留下来。
也许你会发现,只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释
放。如果程序执行结束,并且垃圾回收器一直都没有释放你创建的任何对象的存储空间,则
随着程序的退出,那些资源会全部交还给操作系统。这个策略是恰当的,因为垃圾回收本身
int 呢?但在使用程序库时,把一个对象用完后就“弃之不顾”的做法并非总是安全的。当
然,Java 有垃圾回收器来回收无用对象占据的内存资源。但也有特殊情况:假定你的对象(并
非使用 new)获得了一块“特殊”的内存区域,由于垃圾回收器只知道释放那些经由 new
分配的内存,所以它不知道该如何释放该对象的这块 “特殊”内存。为了应对这种情况,
Java 允许你在类中定义一个名为 finalize( )的方法。它的工作原理“应该”是这样的:一旦
垃圾回收器准备好释放对象占用的存储空间,将首先调用其 finalize( )方法,并且在下一次
垃圾回收动作发生时,才会真正回收对象占用的内存。所以要是你打算用 finalize( ),就能
在“垃圾回收时刻”做一些重要的清除工作。
这里有一个潜在的编程陷阱,因为有些程序员(特别是 C++程序员)刚开始可能会误把
finalize( )当作 C++中的“析构函数”(C++中销毁对象必须用到这个函数)。所以有必要明确
区分一下:在 C++中,对象一定会被“销毁”(如果程序中没有错误的话);而 Java 里的对
象却并非总是被“垃圾回收”的。或者换句话说:
1. 对象可能不被回收。
2. 垃圾回收并不等于“析构”。
牢记这些,你就能远离困扰。这意味着在你不再需要某个对象之前,如果必须执行某些动作,
那么你得自己去做。Java 并未提供“析构函数”或相似的概念,要做类似的清除工作,你必
须自己动手创建一个执行清除工作的普通方法。例如,假设某个对象在创建过程中,会将自
己绘制到屏幕上。要是你不明确地从屏幕上将其擦除,它可能永远得不到清除。如果在
finalize( )里加入某种擦除功能,当“垃圾回收”发生时(不能保证一定会发生),finalize( )
得到了调用,图像就会被擦除。要是“垃圾回收”没有发生,图像就会一直保留下来。
也许你会发现,只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释
放。如果程序执行结束,并且垃圾回收器一直都没有释放你创建的任何对象的存储空间,则
随着程序的退出,那些资源会全部交还给操作系统。这个策略是恰当的,因为垃圾回收本身
也有开销,要是不使用它,那就不用支付这部分开销了。