对象

Java 是一门面向对象的程序设计语言,对象是由类实例化而来的,所有问题都通过对象来处理。对象可以通过操作类的属性和方法来解决相应的问题,因此了解对象的产生、操作和消亡是十分必要的。本节就来讲解对象在 Java 语言中的应用。

对象的创建

在6.1节中曾经讲解过对象,对象可以被认为是在一类事物中抽象出的某一个特例,程序开发人员可以通过这个特例处理这类事物出现的问题。在 Java 语言中,通过 new 操作符创建对象。前文在讲解构造方法时介绍过,每实例化一个对象就会自动调用一次构造方法,实质上这个过程就是创建对象的过程。准确地说,可以在 Java 语言中使用 new 操作符调用构造方法创建对象。语法如下:

Test test = new Test();
Test test = new Test("a");
java

其参数说明如表6.2所示。

image 2024 02 29 16 40 22 891
Figure 1. 表6.2 创建对象语法中的参数说明

test 对象被创建出来时,就是一个对象的引用,这个引用在内存中为对象分配了存储空间。6.3节中介绍过,可以在构造方法中初始化成员变量,当创建对象时,自动调用构造方法。也就是说,在Java语言中,初始化与创建是被捆绑在一起的。

每个对象都是相互独立的,在内存中占据独立的内存地址,并且每个对象都具有自己的生命周期,当一个对象的生命周期结束时,对象就变成垃圾,由 Java 虚拟机自带的垃圾回收机制处理,不能再被使用(对于垃圾回收机制的知识将在6.6.4节中进行讲解)。

在 Java 语言中,对象和实例事实上可以通用。

【例6.7】创建人类并创建其对象(实例位置:资源包\TM\sl\6\7)

创建人类(People类),类中有名字、年龄和性别3个属性,并为People类创建有参和无参两种构造方法。以人类为模板,创建两个对象,分别为23岁名叫tom的小伙子、19岁名叫lily的小姑娘。

public class People {
	String name;
	int age;
	String sex;

	public People() {
	}

	public People(String name, int age, String sex) {
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	public static void main(String[] args) {
		People p1 = new People("tom", 23, "男");
		People p2 = new People("lily", 19, "女");
	}
}
java

访问对象的属性和行为

用户使用 new 操作符创建一个对象后,可以使用 “对象.类成员” 来获取对象的属性和行为。前文已经提到过,对象的属性和行为在类中是通过类的成员变量和成员方法的形式来表示的,因此当对象获取类成员时,也相应地获取了对象的属性和行为。

【例6.8】描述狗的特征(实例位置:资源包\TM\sl\6\8)

在 Dog 类中创建名字、颜色和声音 3 个属性,再创建一个 “叫” 的方法。以 Dog 类为模板创建两只狗,一只是白色且会汪汪汪叫的毛毛,另一只是灰色且会嗷呜叫的灰灰。

public class Dog {// 狗
	String name;// 名字
	String Color;// 颜色
	String vioce;// 声音

	public Dog(String name, String color, String vioce) {
		this.name = name;
		Color = color;
		this.vioce = vioce;
	}

	public void call() {// 叫
		System.out.println(vioce);
	}

	public static void main(String[] args) {
		Dog d1 = new Dog("毛毛", "白色", "汪汪汪");
		System.out.print(d1.name + "的颜色是" + d1.Color);// 访问对象的属性
		System.out.print(",叫起来的声音:");
		d1.call();// 访问对象的行为

		Dog d2 = new Dog("灰灰", "灰色", "嗷呜~");
		System.out.print(d2.name + "的颜色是" + d2.Color);
		System.out.print(",叫起来的声音:");
		d2.call();
	}
}
java

运行结果如下:

     毛毛的颜色是白色,叫起来的声音:汪汪汪
     灰灰的颜色是灰色,叫起来的声音:嗷呜~
bash

对象的引用

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

     类名 对象的引用变量
bash

例如,一个 People 类的引用可以使用以下代码:

     People tom;
java

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

People tom = new People();
java

在上述代码中,各个单词的含义如图6.12所示。

image 2024 02 29 16 45 53 026
Figure 2. 图6.12 代码中各单词的含义

实际上真正的对象是 new People() 这段代码。为了方便开发者保存、调用对象,于是创建了一个 People 类型、名叫 tom 的引用变量。实际上,tom 只是一段内存地址,用于标记 new People() 对象在内存中的位置。因为内存地址又长又乱,很难让人记住,所以 Java 语言利用引用变量帮开发者标记内存地址。开发者只要记住引用变量的名字,就能够在内存里找到对象数据。简单来说,tom 是 new People() 的 “代理人”。

既然 tom 是 new People() 的 “代理人”,那么 new People() 对象能做的事,tom 也能做。例如,下面这行代码:

new People().getClass();
// 等价于
People tom = new People();
tom.getClass();
java

对象的销毁

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

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

  • 对象引用超过其作用范围,这个对象将被视为垃圾,如图6.13所示。

  • 给对象赋值为 null,如图6.14所示。

image 2024 02 29 16 48 51 573
Figure 3. 图6.13 对象超过作用范围将消亡
image 2024 02 29 16 49 41 550
Figure 4. 图6.14 对象被置为null值时将消亡

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

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

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

编程训练(答案位置:资源包\TM\sl\6\编程训练)

【训练9】创建猫类 编写一个猫类,然后分别创建 3 只猫的对象,分别是黑猫、白猫和黄猫,让 3 只猫都去抓老鼠。

【训练10】创建数学工具类 编写一个数学工具类,类中有一个 pow() 方法。当为 pow() 方法传入一个 double 值时,该方法会返回这个值的 4 次幂。利用这个工具类,计算 45.6 和 0.35 的 4 次幂。