构造方法是类中特殊方法,用来初始化类的实例变量,它在创建对象(new运算符)之后自动调用。
Java构造方法的特点如下:
示例代码如下:
1 //Rectangle.java文件
2 package com.a51work6;
3
4 // 矩形类
5 public class Rectangle {
6
7 // 矩形宽度
8 int width;
9 // 矩形高度
10 int height;
11 // 矩形面积
12 int area;
13
14 // 构造方法
15 public Rectangle(int w, int h) {
16 width = w;
17 height = h;
18 area = getArea(w, h);
19 }
20 ...
21 }
代码第15行是声明了一个构造方法,其中有两个参数w和h,用来初始化Rectangle对象的两个成员变量width和height,注意前面没有任何的返回值。
默认构造方法
有时在类中根本看不到任何的构造方法。例如本节中User类代码如下:
1 //User.java文件
2 package com.a51work6;
3
4 public class User {
5
6 // 用户名
7 private String username;
8
9 // 用户密码
10 private String password;
11
12 }
从上述User类代码,只有两个成员变量,看不到任何的构造方法,但是还是可以调用无参数的构造方法创建User对象,因为Java虚拟机会为没有构造方法的类,提供一个无参数的默认构造方法,默认构造方法其方法体内无任何语句,默认构造方法相当于如下代码:
//默认构造方法
public User() {
}
默认构造方法的方法体内无任何语句,也就不能够初始化成员变量了,那么这些成员变量就会使用默认值,成员变量默认值是与数据类型有关。
构造方法重载
在一个类中可以有多个构造方法,它们具体有相同的名字(与类名相同),参数列表不同,所以它们之间一定是重载关系。
构造方法重载示例代码如下:
1 //Person.java文件
2 package com.a51work6;
3
4 import java.util.Date;
5
6 public class Person {
7
8 // 名字
9 private String name;
10 // 年龄
11 private int age;
12 // 出生日期
13 private Date birthDate;
14
15 public Person(String n, int a, Date d) {
16 name = n;
17 age = a;
18 birthDate = d;
19 }
20
21 public Person(String n, int a) {
22 name = n;
23 age = a;
24 }
25
26 public Person(String n, Date d) {
27 name = n;
28 age = 30;
29 birthDate = d;
30 }
31
32 public Person(String n) {
33 name = n;
34 age = 30;
35 }
36
37 public String getInfo() {
38 StringBuilder sb = new StringBuilder();
39 sb.append("名字: ").append(name).append('\n');
40 sb.append("年龄: ").append(age).append('\n');
41 sb.append("出生日期: ").append(birthDate).append('\n');
42 return sb.toString();
43 }
44 }
上述代码Person类代码提供了4个重载的构造方法,如果有准确的姓名、年龄和出生日期信息,则可以选用代码第15行的构造方法创建Person对象;如果只有姓名和年龄信息则可选用代码第21行的构造方法创建Person对象;如果只有姓名和出生日期信息则可选用代码第26行的构造方法创建Person对象;如果只有姓名信息则可选用代码第32行的构造方法创建Person对象。
Tips:如果在类中添加了带参的构造函数,系统就不会在自动生成无参的构造函数,所以建议添加带参数的构造函数后,再手动添加一个默认无参的构造函数。
构造方法封装
构造方法也可以进行封装,访问级别与普通方法一样,构造方法的访问级别参考[ Java学习基础 ] Java的封装性与访问控制中图所示。示例代码如下:
1 //Person.java文件
2 package com.a51work6;
3
4 import java.util.Date;
5
6 public class Person {
7
8 // 名字
9 private String name;
10 // 年龄
11 private int age;
12 // 出生日期
13 private Date birthDate;
14
15 // 公有级别限制
16 public Person(String n, int a, Date d) {
17 name = n;
18 age = a;
19 birthDate = d;
20 }
21
22 // 默认级别限制
23 Person(String n, int a) {
24 name = n;
25 age = a;
26 }
27
28 // 保护级别限制
29 protected Person(String n, Date d) {
30 name = n;
31 age = 30;
32 birthDate = d;
33 }
34
35 // 私有级别限制
36 private Person(String n) {
37 name = n;
38 age = 30;
39 }
40
41 ...
42 }
上述代码第16行是声明公有级别的构造方法。代码第23行是声明默认级别,默认级别只能在同一个包中访问。代码第29行是保护级别的构造方法,该构造方法在同一包中与默认级别相同,在不同包中可以被子类继承。代码第36行是私有级别构造方法,该构造方法只能在当前类中使用,不允许在外边访问,私有构造方法可以应用于单例设计模式等设计。
----------------------------------------------------------------------------
初始化块和构造函数的执行顺序
读者可先自行阅读下面代码,判断输出结果:
1 class B extends Object
2 {
3 static
4 {
5 System.out.println("Load B");
6 }
7 public B()
8 {
9 System.out.println("Create B");
10 }
11 }
12 class A extends B
13 {
14 static
15 {
16 System.out.println("Load A");
17 }
18 public A()
19 {
20 System.out.println("Create A");
21 }
22 }
23
24 public class Testclass
25 {
26 public static void main(String [] args)
27 {
28 new A();
29 }
30 }
输出结果:
Load B
Load A
Create B
Create A
初始化块在构造器执行之前执行,类初始化阶段先执行最顶层父类的静态初始化块,依次向下执行,最后执行当前类的静态初始化块;创建对象时,先调调用顶层父类的构造方法,依次向下执行,最后调用本类的构造方法 。所以执行顺序为:父类静态代码 -> 子类静态代码块 -> 父类构造代码块 -> 父类构造函数 -> 子类构造代码块 -> 子类构造函数