4.2 类与对象
4.2.1 类
在面向对象的语言中,类是个很重要的概念。面向对象的方法把所有的处理对象进行归类。具有相同性质的对象归为一类。例如学校里有很多学生,每个学生都是一个对象,而“学生”则是一个类,它包含了所有在学校学习的人。
在Java语言里,对象是一组描述对象的属性和操作方法的集合,其中属性表明对象的状态,方法表明对象的行为。类是对象的定义。一个对象具有哪些属性和方法,由类来决定。从编程角度看,类是一种复合数据类型,它封装了一组变量和方法(函数)。
声明一个类的一般形式如下所示:
修饰符 class 类名{
//类体
}
其中修饰符说明了类的属性,可以是public、abstract、final等。这些修饰符的含意将会在后继的章节中介绍。类体就是类的成员变量和成员方法的声明。修饰符和类体的声明都是可以选的。下面是一个“人”的类的声明,虽然类体是空的:
class Person{
}
4.2.2 对象
对象与类是不同但是又紧密相联的概念。类是对象的定义,对象由类来生成。类与对象的关系好比铸造车间里模具与产品的关系。模具只有一个,但是用这个模具可以浇铸出很多成型的产品出来,模具的外形决定了浇铸出来的产品的外形。在Java语言里用new要害字来生成对象,通常的格式为:
类名 对象名=new 类名([参数]);
这里的对象名可以是任意合法的Java标识符。new要害字后带小括号的类名称为构造方法(函数)。默认的、也是最简单的构造方法是不带参数的,也可以自定义不同形式的构造方法以供不时之需。下例利用刚才的Person类来生成两个Person对象Mike和John:
Person Mike=new Person();
Person John=new Person();
用new Person()生成一个对象时不仅分配了内存空间还进行了一些初始化的工作,对象所包含的不仅只是各个属性名了,而是属性的具体值。假如没有给属性赋值,虚拟机会自动给它们赋于相应数据类型默认的初值。生成一个对象的过程也称为实例化,所以一个对象就是一个实例。Mike和John是对象名,对象名是用来引用对象的,对象里的变量和方法可以通过对象名来引用,所以对象名也称为引用(Reference)。引用类似于C/C++中指针的概念,与指针不同,引用不是直接指向对象所在的内存位置,但是它包含了内存地址的信息。Java中并没有指针,以指针进行内存操作常造成不预知的错误,还可能破坏安全性,也正是因为如此,Java被认为是“安全的”编程语言。上例中生成的对象和引用如下图所示:
图4-1 引用与对象
在某些非凡的情况下,可能生成实例但不需要引用,那可以直接用new来实例化。如下所示:
new Person();
new Person();
上面两行程序生成两个Person对象,但是每次生成的对象分别占用不同的内存空间,改变其中一个对象的状态不会影响其它对象的状态。就象每次用模具倒出一个毛坯一样, 尽管两个毛坯看起来很象,但它们绝对是两个不同的毛坯。
4.2.3 成员变量
在面向对象的思想中,通常用属性来描述对象的特征。在编程语言里,这一组从属于某类对象的属性是用变量来表示的,例如前文提到用来表示人的特征的身高、体重、姓名等等,就可以分别用不同类型的变量:double型的height、float型weight、String型的name来表示。这些属于类的变量,称为类的成员变量。
声明成员变量的一般形式如下:
修饰符 数据类型 成员变量名;
其中修饰符说明了类的成员变量的属性,可以是public、protected、private、static、transient、final、volatile等等。成员变量的类型可以是Java内置的或者是自定义的复杂数据类型,包括简单类型、类、接口、数组。例如,描述一个人有一座房产可以用House类型的变量house来表示,这里的House是用户自定义的类(复杂数据类型)。调用成员变量的一般形式是:
实例名.成员变量名
下面是一个“人”的类的声明,类名是Person。描述“人”的成员变量有:height、weight、sex、name、age等,还有房产house的声明。
【例4-1】
class Person{
double height;
float weight;
char sex;
String name;
int age;
House house;
}
class House{}
public class E4_1{
public static void main(String args[]){
Person p_Bill=new Person();
p_Bill.age=26;
p_Bill.height=180;
p_Bill.weight=145;
p_Bill.sex='m';
p_Bill.name="Bill Gates";
p_Bill.house=new House();
}
}
Person类有6个成员变量,其中5个是简单数据类型,1个是复合数据类型House。在类E4_1的main函数里生成了一个引用名为p_Bill的对象。通过这个p_Bill这个引用可以访问到这个人的年龄、身高、体重等属性。
上例的程序可以在全部放在一个源文件中,源文件名为必须为E4_1。Java的一个源文件答应多个类的存在,但是文件名必须和public类一致,一个源文件中只也能有一个public类。
成员变量不需要显式初始化可以直接使用。其实,它们还是有被初始化过的,称为隐式的初始化。没有显式初始化的成员变量是在为对象分配存储空间时自动被初始化,各种类型的变量被赋于默认的初始化值,如下所示:
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'(null)
boolean false
所有复合数据类型 null
下例打印了隐式初始化的Person类成员变量。