Java 中的对象与引用
Contents
更好的理解 Java 中的 对象 和 引用 是面向对象技术的前提,本文旨在讨论如何理解它们的含义以及它们之间的关系。如有错误,还请指出。
对象
在《编程思想》中说到:**对象是某个类(class)的一个实例(instance)。**如果单纯的理解这句话,我们可以说:对象是类所产生的实例。例如对于 人类 这一类别来说,小明 这一具体的对象就是 人类 产生的 实例。
为了便于理解,我们首先定义一个简单的类:
|
|
然后可以使用以下语句创建对象:
|
|
这是我初次学习 Java 面向对象的时候,视频中的老师给出的引子。对于一个 类 来说,它是构造对象的模板和蓝图。而通过 类 来构造对象的过程称为 创建类的实例,也叫 实例化。
上面的语句创建了一个对象,有如下几步:
new Person是以Person类为模板或者蓝图,在堆空间中创建了一个Person类对象;- 后面的
()表示在创建对象后,调用了Person类中的构造函数,对刚刚创建的对象进行初始化操作;
此时,我们再看如下代码:
|
|
这看似和上面的代码没有什么差别,但更方便理解。这里首先创建了一个 Person 类型的引用变量 p,然后用对象的引用 p 通过 = 操作符指向刚才创建的 Person 对象。
很显然,这里的 p 是对象的一个引用,是一个可以指向 Person 类的对象的引用,而不是所创建的对象,真正创建对象的语句是 new Person()。
引用
一个 Person 类可以创建出无数的对象,我们只能通过 对象引用 来间接访问对象。这里做一个形象的比喻:一根绳子系住气球。我们将 对象 比作气球,将 引用变量 比作绳子。
如果仅执行 Person p; 语句的话,此时创建的一个引用变量 p 还没有指向任何一个对象,其默认是 null。这就相当于一根还没有系住任何气球的绳子。如果执行了 p = new Person(); 语句,则就可以说明对象引用 p 指向了一个对象,也就是绳子系住了气球。
此时,再声明一个 Person 类型的引用,如下所示:
|
|
表示又做了一根绳子,但是还没有系上气球。如果再加上一句 p1 = p;,则说明系上了气球。因为这里对象没有被复制,而是对象的引用被复制了,所以 p1 也指向了 p 所指的对象。两根绳子(p 引用 和 p1 引用)系上的是同一个气球(对象)。
如果执行了以下语句:
|
|
则说明 p1 这一引用指向了另外一个对象,即另一个气球。
此时,可以得到:
- 一个引用可以指向 0 个或 1 个对象,即一根绳子可以不系住气球,也可以系住一个气球;
- 一个对象可以被多个引用指向,即一个气球可以被多个绳子系住。
此时,再执行下面的语句:
|
|
同理,p 指向了第二个对象,也就是说,p 指向了 p1 所指的对象。那么第一个对象去哪儿了呢?第一个气球没有绳子了,它往哪儿飞了呢?其实,第一个对象被 Java 中的垃圾回收机制给回收了。
好了,现在我们不看上面的语句,只看下面的语句:
|
|
这样写也是合法的,表明生成一个临时对象,只是没有引用变量来引用它而已。
例子
创建一个对象
为了更详细的说明 Java 创建对象的过程,可以参考以下图像:

如上图所示,左侧表示代码,右侧表示其在 Java 虚拟机中具体的表现形式。关于 JVM 的内存区域这里不再做详细的解释,你可以查看笔者的《Java 内存区域概述》这篇文章。
这里解释一下代码执行的流程:
- 首先
Demo1_Car类中的 main 方法进入方法区,当遇到Car c1 = new Car();语句的时候,Car类及其内部的成员变量和成员方法也进入到方法区; - 然后开始在堆中创建对象,并且
对象引用 c1指向堆中的地址为0x0011; - 由于刚刚创建对象,所以需要将对象进行初始化,则引用类型的
color一开始的默认值是null,基本数据类型的num一开始的默认值是0; - 经过
c1.color = "red";以及c1.num = 8;语句后,color被修改为red,num被修改为8; - 最后在栈中,也就是 main 函数的上面压入一个
run()方法(图中未画出); - 这里最重要的就是
c1是对象的一个引用,就像绳子一样。
创建两个对象
下面给出创建两个对象,具有三个引用的示例:

流程和上面的大体相同:
- 在执行到
Car c1 = new Car();语句的时候,堆中先创建了一个地址为0x0011的对象,并且栈中的c1指向第一个对象的地址,即0x0011; - 执行到
Car c2 = new Car();语句的时候,堆中也是先创建了另外一个地址为0x0022的对象,栈中的c2指向第二个对象的地址,即0x0022; - 执行到
Car c3 = c2;的时候,先生成一个对象引用c3,然后c3指向和c2同样的地址,即0x0022,此时c2和c3指向的就是同一个对象。
以上就是对 Java 中的 对象 以及 对象的引用 进行的总结,理解这些对于 Java 中的值传递是非常有意义的。