对于Java对象的构造和初始化过程的理解,我们可以先掌握如下规则:
1)在进入main方法之前类加载时,执行static修饰的静态代码块,并且只执行一次。先执行父类静态代码块再执行子类静态代码块。
2)执行父类初始化块(游离块),构造方法。
本文引用地址:http://www.hqyj.com/emb/Column/7449.html
初始化块,每创建一个对象调用一次。
如果构造方法中使用this()调用其他构造方法,该行代码必须放在构造方法中第一行。
3)执行子类初始化块(游离块),构造方法。
初始化块,每创建一个对象调用一次。
在子类构造方法中,如果没有通过super显式调用父类构造方法,则默认调用父类无参构造方法;如果通过super显示调用父类构造方法,该代码必须放在第一行。
举例说明如下:
创建父类Person.java
public class Person {
private String name;
private int age;
private String sex;
static{
System.out.println("这是静态代码块Person");
}
{
System.out.println("这是自由代码块Person");
}
//第一个构造方法
public Person(){
System.out.println("Person()");
}
//第二个构造方法
public Person(String name,int age){
System.out.println("Person(String name,int age)");
this.age = age;
this.name = name;
}
//第三个构造方法
public Person(String name,int age,String sex){
this(name,age);
System.out.println("Person(String name,int age,String sex)");
this.sex = sex;
}
}
创建子类Student.java
public class Student extends Person {
static{
System.out.println("这是静态代码块Student");
}
{
System.out.println("这是自由代码块Student");
}
//第一个构造方法
public Student(String name,String sex,int age){
super(name,age,sex);
System.out.println("Student(String name,String sex,int age)");
}
//第二个构造方法
public Student(){
System.out.println("Student()");
}
}
创建测试类Test.java
public class Test {
public static void main(String[] args) {
Student s = new Student("violet","female",33);
Student s1 = new Student();
}
}
运行输出结果如下:
这是静态代码块Person //第一行
这是静态代码块Student //第二行
这是自由代码块Person //第三行
Person(String name,int age) //第四行
Person(String name,int age,String sex) //第五行
这是自由代码块Student //第六行
Student(String name,String sex,int age) //第七行
这是自由代码块Person //第八行
Person() //第九行
这是自由代码块Student //第十行
Student() //第十一行
解释说明如下:
1)在类加载时,也就是执行main方法之前执行静态代码块,只执行一次,所以输出//第一行、//第二行。
2)当我们执行main函数中Student s = new Student("violet","female",33);语句时,先调用父类初始化块,输出//第三行。
再调用父类构造方法,在Studet.java第一个构造方法中通过super(name,sex,age)调用父类Person.java中第三个构造方法,该构造方法中第一行代码this(name,age)指向第二个构造方法,所以先执行第二个构造方法,输出//第四行。第二个构造方法执行结束,返回到第三个构造方法,输出//第五行
父类构造方法执行完毕,返回到Student.java类。先执行初始化块,输出//第六行。再执行第一个构造方法里,输出//第七行。
3)当我们执行main函数中Student s1 = new Student();语句时,先调用父类初始化块,输出//第八行。
再执行父类构造方法,在Student.java第二个构造方法里,没有通过super()显示调用父类某个构造方法,此时默认调用父类无参构造方法。所以输出//第九行。
父类构造方法执行完毕,返回到Student.java类。先执行初始化块,输出//第十行。再执行第二个构造方法,输出//第十一行。