Java对象的引用、比较、销毁

对象的引用

在Java语言中尽管一切都可以看作对象,但真正的操作标识符实质 上是一个引用,那么引用在Java中是如何体现的呢?来看下面的语法。 语法如下:

类名 对象引用名称

如一个Book类的引用可以使用以下代码:

Book book;

通常一个引用不一定需要有一个对象相关联。引用与对象相关联的 语法如下:

Book book=new Book();
  • Book:类名。
  • book:对象。
  • new:创建对象操作符。

注意:引用只是存放一个对象的内存地址,并非存放一个对象。严格地 说,引用和对象是不同的,但是可以将这种区别忽略,如可以简单地 说book是Book类的一个对象,而事实上应该是book包含Book对象的一 个引用。

对象的比较

在Java语言中有两种比较对象的方式,分别为“==”运算符与equals() 方法。这两种方式有着本质区别,下面举例说明。

【例】在项目中创建Compare类,该类说明了“==”运算符与 equals()方法的区别。

public class Compare {
	public static void main(String[] args) {
		String c1 = new String("abc"); // 创建两个String型对象引用
		String c2 = new String("abc");
		String c3 = c1; // 将c1对象引用赋予c3
		// 使用“==”运算符比较c2与c3
		System.out.println("c2==c3的运算结果为:" + (c2 == c3));
		// 使用equals()方法比较c2与c3
		System.out.println("c2.equals(c3)的运算结果为:" + (c2.equals(c3)));
	}
}

在Eclipse中运行本例,结果如图所示。

比较两个对象引用的运行结果
比较两个对象引用的运行结果

从上述运行结果中可以看出,“==”运算符和equals()方法比较的内 容是不相同的,equals()方法是String类中的方法,它用于比较两个对象 引用所指的内容是否相等;而“==”运算符比较的是两个对象引用的地址 是否相等。由于c1与c2是两个不同的对象引用,两者在内存中的位置不同,而“String c3=c1;”语句将c1的引用赋给c3,所以c1与c3这两个对象引 用是相等的,也就是打印c1==c3这样的语句将返回true值。对象c1、c2 和c3在内存中的布局如图所示。

对象c1、c2和c3在内存中的布局
对象c1、c2和c3在内存中的布局

对象的销毁

每个对象都有生命周期,当对象的生命周期结束时,分配给该对象 的内存地址需要被回收。在其他语言中,需要用户手动回收废弃的对 象。Java拥有一套完整的垃圾回收机制,用户不必担心废弃的对象占用 内存,垃圾回收器会自动回收无用却占用内存的资源。

在学习垃圾回收机制之前,读者首先需要了解何种对象会被Java虚 拟机视为“垃圾”。主要包括以下两种情况:

  • 对象引用超过其作用范围,这个对象将被视为垃圾,如图1所示。
  • 将对象赋值为null,如图2所示。
对象超过作用范围将消亡
图1 对象超过作用范围将消亡
对象被置为null值时将消亡
图2 对象被置为null值时将消亡

虽然垃圾回收机制已经很完善,但垃圾回收器只能回收那些由new 操作符创建的对象。某些对象不是通过new操作符在内存中获取存储空 间的,这种对象无法被垃圾回收机制所识别。在Java中提供了一个 finalize()方法,这个方法是Object类的方法,它被声明为protected,用户 可以在自己的类中定义这个方法。如果用户在类中定义了finalize()方 法,在垃圾回收时会首先调用该方法,在下一次垃圾回收动作发生时, 才真正回收被对象占用的内存。

说明:需要明确的是,垃圾回收或finalize()方法并不保证一定会发生。如 果Java虚拟机内存损耗待尽,它将不会执行垃圾回收处理。

由于垃圾回收不受人为控制,具体执行时间也不确定,所以finalize()方法也就无法执行。为此,Java提供了System.gc()方法来强制启动垃圾回收器,这与给120打电话通知医院来救护病人的道理一样, 主动告知垃圾回收器来进行清理。

发表评论