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 中的值传递是非常有意义的。