关于对象构造的一些认识。
默认域初始化
如果在构造器中没有显示地给域赋予初值,那么就会被自动地赋予默认值:数值为0,布尔值为false,对象引用为null。然而,这显然是不安全的,在一个null引用上调用方法结果是不可预期的。
class Employee{ private String name; private double salary; }
无参数构造器
每个类都包含一个无参数构造函数,对象由无参数构造函数创建时,其状态会设置为适当的默认值。如果程序没有编写构造器,则这个构造器会将所有实例域设置为默认值:数值为0,布尔值为false,对象引用为null。
如果类中提供了至少一个构造器,但是没有提供无参数构造器,那么在构造对象时没有提供参数将视为不合法。也就是说:仅当类没有提供任何构造器时,系统才会提供一个默认的构造器。
class Employee{ private String name; private double salary; public Employee(){ //相当于系统提供的默认构造函数 this.name = null; this.salary = 0; } }
显示域初始化
显示地设置类的实例域的初始状态,确保不管调用任何构造器,每个实例域都可以设置为一个有意义的值,这是一种良好的设计习惯。
class Employee{ private String name="张三"; private double salary=30000; public Employee(){ this.name = "张三"; this.salary = "30000" }
构造器方法重载
如果多个方法有相同的名字,不同的参数,便产生了重载。构造器方法也支持重载。编译器通过用各个方法给出的参数类型和特定方法调用所使用值的类型进行匹配来执行相应的方法。若无匹配则会产生编译错误。
class Employee{ private String name; private double salary; public Employee(){ //构造器一 this.name = "张三"; this.salary = "30000" } public Employee(string name){ //构造器二 this.name = name; this.salary = "20000"; } }
调用另一个构造器
如果构造器第一个语句形如this(...),这个构造器将调用同一个类的另一个构造函数。
class Employee{ private String name; private double salary; public Employee(double salary){ //构造器一 this("李四",salary); //将调用构造器二 } public Employee(String name,double salary){ //构造器二 this.name = name; this.salary = "20000"; } }
初始化块和初始化语句
在一个类的声明中,可以包含多个代码块,只要构造对象,这些块就会被执行。
class Employee{ private String name="李四"; //初始化语句 private double salary; { //初始化块 salary = "10000"; } public Employee(){ this.name = "张三"; this.salary = "30000" } }
调用构造器的具体步骤:
1)所有数据域被初始化为默认值
2)按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块。
3)如果被调用的构造器第一行调用了另一个构造器,则执行那个构造器主体。
4)执行这个构造器主体。
实例:
1 import java.util.Random; 2 3 4 public class ConstructorTest{ 5 public static void main(String[] args){ 6 Employee[] staff = new Employee[3]; 7 8 staff[0] = new Employee("Harry",40000);//调用构造器一 9 System.out.println("name=" + staff[0].getName() +",id=" + staff[0].getId() + ",salary=" + staff[0].getSalary()); 10 staff[1] = new Employee(60000);//调用构造器二 11 System.out.println("name=" + staff[1].getName() +",id=" + staff[1].getId() + ",salary=" + staff[1].getSalary()); 12 staff[2] = new Employee();//调用构造器三,与不提供构造器时系统的默认构造器相同 13 System.out.println("name=" + staff[2].getName() +",id=" + staff[2].getId() + ",salary=" + staff[2].getSalary()); 14 } 15 } 16 17 18 class Employee { 19 private static int nextID; 20 private int id; 21 private String name="";//初始化语句 22 private double salary; 23 24 static { //静态初始化块 25 System.out.println("静态块初始化"); 26 Random generator = new Random(); 27 nextID = generator.nextInt(10000); 28 } 29 { //初始化块 30 System.out.println("普通初始化块"); 31 id = nextID; 32 nextID++; 33 } 34 35 public Employee(String name,double salary){//构造器一 36 this.name = name; 37 this.salary = salary; 38 } 39 40 public Employee(double salary){//构造器二 41 this("Emploee #" + nextID, salary); 42 } 43 44 public Employee(){//构造器三 45 46 } 47 48 public String getName() { 49 return name; 50 } 51 52 public double getSalary() { 53 return salary; 54 } 55 56 public int getId() { 57 return id; 58 } 59 }
运行结果:
静态块初始化
普通初始化块
name=Harry,id=5376,salary=40000.0
普通初始化块
name=Emploee #5377,id=5377,salary=60000.0
普通初始化块
name=,id=5378,salary=0.0
静态块只运行了一次的原因时因为静态块在类加载时运行的,而不是在创建对象时运行的。在程序的整个生命期值也只运行一次。详情可看java类加载过程。