1.类与对象

1.类与对象

(1)定义类的作用

每种计算机语言都有自己的数据类型,但是数据类型的种类都很有限。Java的基本数据类型有4种:整型、浮点型、字符型、布尔型。我们编写程序是为了管理和处理数据对象,而我们面对的对象是多种多样的。例如,我们在做一个公司人员信息管理系统时,面对的对象是公司员工,对每个员工需要管理若干数据:员工编号、姓名、性别、出生日期、所属部门、电话号码等。假设,一个员工需要6个变量来存储信息,那么100个员工就有600个变量。在这种情况下,每个员工并不是一个整体,而是由若干数据组成的,这就造成数据总的个数多,数据的结构松散。当员工属性需要修改时,如再加入一项QQ号码等,那么就需要在员工出现的所有地方都做修改。

如果有一个叫作“员工”的数据类型,就可以用“员工”类型来定义“员工”变量,那么就把每个员工当成了整体来操作,这样数据的粒度增大了,数据的数量减少了,编程的复杂度下降了。

在“员工”类型中,将统一定义“员工”具有的属性以及“员工”遵守的操作方法。每一个“员工”实例对象,都包含“员工”类型中定义的属性,都可以通过调用“员工”类型中定义的操作方法进行操作。

Java中肯定没有一个基本数据类型叫作“员工”,程序员需要自己根据面向的对象,抽取对象的共同属性和行为来定义数据类型,我们把这些自定义数据类型叫作类,用自定义数据类型定义的变量叫作对象。

现在,让我们来学习怎样定义一个自定义数据类型——类,怎样用类来定义变量——对象。

(2)类的定义方法

【代码15.1】

需求:定义“矩形”类,这个类包含共通的属性——矩形的长和矩形的宽,包含共通的操作方法——求矩形的周长和矩形的面积。

在代码15.1中,第1行到第14行定义了一个Rectangle类,作为一个数据类型,Rectangle类规定了所有的“矩形”对象,“矩形”对象都有width(宽)和height(高)两个属性,也叫作成员变量,见第2行和第3行。Rectangle类也规定了所有“矩形”对象求面积的方法〔get Area()〕和求周长的方法〔getPerimeter()〕,见第5行到第13行。

类的定义由两部分内容组成:属性(叫作成员变量)和方法(叫作成员方法)。属性和方法定义了一个类所有具体对象共同具有的属性和共同遵循的行为。

(3)类和对象

Rectangle是一个类(可以理解为自定义数据类型),类可以用来定义一个对象(等同于之前的变量)rectangle,见代码15.1的第19行。

我们看到,自定义数据类型定义对象和内置数据类型定义对象的方法是不同的。

①内置数据类型定义对象

形如:

double a=3.14;

给变量a分配内存空间,然后通过赋值在空间中存入3.14。

②自定义数据类型定义对象

形如:

Rectangle rectangle=new Rectangle();

赋值号左边的Rectangle rectangle定义了Rectangle类的对象rectangle,分配了内存空间,用来保存rectangle对象的首地址,这叫作引用;赋值号右边的new Rectangle()申请了实际的对象空间(包括width和height的空间),然后将对象空间的首地址赋值给引用空间。

用new开辟的内存空间和不是用new开辟的内存空间的管理方式是不同的,前者属于堆空间,后者属于栈空间。

类定义对象时,内存分配的过程如下。

第一,在栈中开辟一个空间给rectangle对象,叫作引用空间。这个引用空间用来存放rectangle对象的首地址,在没有赋值之前,引用空间中的值是随机值。

第二,用new开辟对象的实际空间。这个实际空间包括为width和height开辟的空间。用new开辟的空间属于堆空间,堆空间有默认初值,这里width和height是double类型,默认初值都是0.0。在类(class)中定义的成员变量〔如width(宽)和height(高)〕在类的内部是可以直接访问的。在类的外部,成员变量要用“对象名.变量名”的形式来访问,见代码15.1的第20行和第21行。

第三,将对象的引用(对象空间的首地址)赋值给rectangle对象的引用空间。

因此,所有的对象名在本质上指代的是对象的引用,自定义类型均可以统称为引用类型。

通过图3.15.1来区别两种变量在内存分配空间的不同。

注意:在图3.15.1中,箭头表示的意思是,箭头指向空间的首地址保存在箭尾所在的空间。

图3.15.1 局部变量和成员变量的内存空间

栈空间和堆空间是两种管理方式不同的内存区域,主要的区别如下。

①栈空间没有默认初值,没有赋值之前是随机值;堆空间有默认初值,默认初值由数据类型决定(整型是0,浮点类型是0.0,布尔类型是false,字符类型是′\0′,引用类型是null)。

②局部变量保存在栈空间中,在变量生命周期结束的时候,自动回收;成员变量保存在堆空间中,当对象成为没有引用指向的“垃圾”时,由Java垃圾收集进程负责回收。例如,上例中的rectangle变量是在main()函数中定义,当main函数结束时,rectangle变量空间会自动释放,而之前rectangle中保存着对象空间的宜地址,当rectangle变量被释放后,对象空间就变成没有引用指向的“垃圾”,由Java垃圾收集进程负责回收。

要注意遵守Java的命名规范,所有类名的首字母要大写,若类名由多个单词组成,则每个单词的首字母要大写。对象名、变量名、方法的首字母要小写,若其由多个单词组成,则从第二个单词开始每个单词的首字母要大写。

封装

getter()/setter()