目录
1. 对象的创建
2. 对象的使用
3. 对象的赋值
4. 对象的销毁
在前一节,我们介绍了Java中类的定义(Java中类的定义),本节介绍如何创建和使用对象。
1. 对象的创建
类定义了一种新的数据类型,完成类的定义后,就可以使用这种新数据类型来创建对象。创建对象的一般语法格式如下:
类名 对象名 = new 类名([参数列表]);
创建对象可分为两个部分:对象声明和对象实例化。对象声明是在内存中为其建立一个引用(通过对象名来表示),其值为null或空,表示不指向任何内存空间;对象实例化是用通过new运算符调用相应的构造方法为对象申请内存空间,内存空间的大小依据类的定义而定,并将该段内存空间的首地址赋给刚刚建立的引用。
例如,下面代码是创建一个矩形类(Rectangle)对象(类Rectangle的定义)。
Rectangle rectangle1=new Rectangle(4.5,2.0);
其中,rectangle1为对象名称,通过调用带参数的构造方法Rectangle(double a,double b)来完成该对象的初始化。
对象声明和对象实例化可以分成两步来完成,其语法格式如下:
类名 对象名;
对象名 = new 类名([参数列表]);
例如,前面创建矩形对象的语句可以改为:
Rectangle rectangle1; //对象声明
rectangle1=new Rectangle(4.5,2.0);//对象实例化
当使用类Rectangle声明对象时,它在内存中还没存放任何值,其内存模型如图1所示,此时,引用rectangle1的值为空。当执行下面语句后
rectangle1=new Rectangle(4.5,2.0);
在内存中为该对象分别配了相应的地址空间,成员变量length和width被赋初值4.5和2.0,这个地址空间的首地址被放到引用rectangle1内,此时的内存模型如图2所示。
图1.对象声明内存模型 图2. 对象实例化内存模型
通过使用new运算符,一个类可以创建多个对象,每个对象被分配的不同的内存空间,因此,改变一个对象的变量不会影响其它对象的变量。
每个类都有一个不带参数的默认构造方法,当通过new运算符调用默认构造方法创建对象时,系统会自动初始化所分配的内存空间。对于数值变量,赋初值0,对于布尔变量,赋初值false,对于引用变量,赋予一个特殊的值null。
2. 对象的使用
对象被创建之后,就可以使用该对象。通过运算符“.”,对象可以实现对自己变量的访问和方法的调用。
对象对自己变量访问的语法格式如下:
对象名.变量名;
对象对自己方法调用的语法格式如下:
对象名.方法名([参数值列表]);
【例1】对象的创建与使用
在Java中,null表示应用没有指向任何对象,运行过程中系统如果发现使用了这样一个引用时,会产生程序运行异常。例如,下面程序在运行时由于的rectangle1值为null而引发一NullPointerException异常。
package graph;
public class Application1 {
static Rectangle rectangle1;
public static void main(String[] args) {
System.out.println(rectangle1.length);
}
}
3. 对象的赋值
Java把说明为class类型的变量看作是引用,其赋值的含义与基本数量类型变量的赋值发生了很大的变化。看下面的代码段,思考一下输出结果是什么?
程序的运行结果为:
r1.length=5.0,r1.width=3.5
r2.length=5.0,r2.width=3.5
创建对象r1的内存模型如图3所示。将对象r1的值赋给对象r2后,它们都指向同一内存地址,如图4所示。修改对象r2的变量值也会影响到对象r1的相应变量值,因此,执行语句r2.length=5.0和r2.width=3.5后,r1.length的值变为5.0,r1.width的值变为3.5,如图5所示。
图3. 创建对象r1内存模型
图4. 将对象r1的值赋给对象r2内存模型
图5. 修改对象r2的变量值后的内存模型
4. 对象的销毁
对象的销毁是指当对象使用完毕后,释放对象所占用的资源。Java虚拟机(JVM)能够自动判断系统中的每个对象是否在使用,并自动销毁不再被使用的对象,收回其所占用的资源,这就是Java的“自动垃圾回收机制”。自动垃圾回收机制是Java非常重要的特性之一,它让程序员无需关注内存空间的创建和释放,而是以守护进程的形式在后台自动回收“垃圾”,这种方式不仅可以提高了开发效率,而且能够改善了内存的使用状况。所谓的“垃圾”就是指所有不再存活的对象(不在被引用的对象)。JVM是如何知道一个对象是否存活?常见的判断对象是否存活的方法主要有两种:引用计数法和可达分析性分析。
引用计数法为每一个创建的对象分配一个引用计数器,用来存储该对象被引用的次数。当该对象被增加一次引用时,引用计数器加1,相反,若对该对象减少一次引用,则引用计数器就减1,当一个对象的引用计数器减到0时,可以认为该对象不再存活。但是,这种方案存在严重的问题,就是无法检测“循环引用”:当两个对象互相引用时,即使它们都不被外界所引用,它俩的计数器都为0,因此永远不会被回收。因此,目前的JVM都不采用这种方法判断对象是否存活,而是采用可达分析性分析。
可达分析性分析的基本思想通过一系列的称为“GC Roots”的对象作为起点,搜索这些节点引用的对象,以及这些引用对象内部属性引用的对象,相当于从一个树形结构的根部进行遍历。节点所走过的路径称为引用链,当一个对象处于引用链上,就被判断为可用对象,例如,图3.6中的Object1、Object2、Object3和Object4。当一个对象到所有的GC Roots没有任何引用链相连时,则说明该对象时不可达的,即判定为该对象已死,例如,图6中的Object5、Object6和Object7。目前JVM都是采用这种方式进行垃圾对象的判断的。
图6. 对象引用树示意图
在Java中,可作为GC Roots的对象包括以下几种:
(1)虚拟机栈中引用的对象
(2)方法区中静态属性引用的对象
(3)方法区中常量引用的对象
(4)本地方法栈中JNI引用的对象
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/25233.html