
5.4 构造方法
从前面所讲解的全部代码可以发现,实例化一个类的对象之后,如果要为这个对象中的属性赋值,则必须通过setter()方法才可以,那么有没有一种简单的方法,可以在对象实例化时就直接把对象的值赋给属性呢?此时,就可以通过构造方法完成这样的操作,在面向对象程序中构造方法的主要作用是为类中的属性初始化。
可以来回顾一下之前对象的产生格式,例如,现在要产生一个类的对象,则必须使用以下格式的代码:

从格式中发现,在最后有一个类名称()的代码,在程序中只要是一看见有“()”就表示调用方法,那么这个方法实际上就是表示要调用构造方法,构造方法可视为一种特殊的方法,它的定义方式与普通方法类似,其语法如下所示:
【格式5-5 构造方法定义格式】

在构造方法的声明中读者一定要牢记以下几点:
(1)构造方法的名称必须与类名称一致;
(2)构造方法的声明处不能有任何返回值类型的声明;
(3)不能在构造方法中使用return返回一个值。
提示
关于访问权限
在这里需要说明的是,对于访问权限,现在实际上本书只使用了3种,即default(默认,什么都不写)、private、public,这3种都可以使用,为了以后的代码开发方便,本段内容暂时使用public访问权限,具体的区别在以后的部分会为读者说明。
【例5.11】声明一个构造方法

程序执行结果:

程序实例化对象的过程与之前是一样的,在类中定义出了一个Person类的构造方法,但是从程序的运行结果可以发现,当调用关键字new实例化对象的时候才会调用构造方法。
有些读者会觉得很奇怪,之前的类中并没有写构造方法,但是也可以调用,这是为什么呢?首先必须跟读者说明的是,只要是类就必须存在构造方法,在Java中如果一个类中没有明确的声明一个构造方法则在编译的时候会直接生成一个无参数的、什么都不做的构造方法,也就是说,如果以上的Person类中没有明确的声明构造方法,实际上编译之后的类就会为用户自动加上以下形式的构造方法:


图5-9 构造方法的类图表示
正因为如此,所以前面的程序中即使没有构造方法,对象也是可以进行对象的实例化操作的。对于构造方法类图没有特别明确的要求,以上的程序直接使用以下的类图形式表示即可,如图5-9所示。
下面范例为通过构造方法为类中的属性赋值。
【例5.12】通过构造方法为属性赋值

程序执行结果:

以上的程序就是直接通过构造方法进行赋值,可以发现,这样赋值比对象实例化之后再单独调用setter方法更方便。
注意
关于自动生成构造方法的说明。
要提醒读者的是,在一个类中如果已经明确地声明了一个构造方法,那么程序在编译时将不会再生成默认的构造方法,即:一个类中至少会存在有一个构造方法。
与普通方法一样,构造方法也是可以重载的,由于构造方法名称本身要求与类名称保持一致,所以只要每个构造方法的参数类型或参数个数不同,就可以实现重载了。
【例5.13】构造方法重载

程序执行结果:

以上类的构造方法被重载了3次,在主方法调用的是只有一个参数的构造方法(只设置姓名),因为没有设置年龄,所以年龄为默认值0。
注意
注意编写顺序。
在一个类中对构造方法重载时,所有的重载的方法按照参数的个数由多到少,或者是由少到多排列,即:以下的两种排列方式都是规范的:

以上的两种写法都是按照参数的个数进行排列的,但是以下的写法就属于不规范定义:

当然,编写不规范并不是语法错误,上面的3种定义,全部都是正确的,但是考虑到程序阅读的方便,请严格遵守以上规定。