Java中构造方法和代码块的执行顺序
程序员文章站
2023-12-09 20:08:09
PS:这两天学了构造方法和代码块,于是把上课学到的东西和笔记做一个整理,归纳一下Java中构造方法和代码块在创建对象的时候执行顺序。废话不多说,上才艺。首先了解一下构造方法和代码块:构造方法构造法和类名一致,其功能主要是完成给对象初始化构造方法又分为两种:1.空参构造2.有参构造二者的区别在于,你在创建对象的时候有没有写参数,写了参数就调用有参构造,没写就调用空参构造。初始化块Java中的初始化块在创建Java对象时隐式执行,并且是在构造函数之前执行。初始化块与构造方法本质....
PS:这两天学了构造方法和代码块,于是把上课学到的东西和笔记做一个整理,归纳一下Java中构造方法和代码块在创建对象的时候执行顺序。废话不多说,上才艺。
首先了解一下构造方法和代码块:
构造方法
构造法和类名一致,其功能主要是完成给对象初始化
构造方法又分为两种:
1.空参构造
2.有参构造
二者的区别在于,你在创建对象的时候有没有写参数,写了参数就调用有参构造,没写就调用空参构造。
初始化块
Java中的初始化块在创建Java对象时隐式执行,并且是在构造函数之前执行。
初始化块与构造方法本质上是一样的,都是传地址,并为对象属性进行初始化
初始化块也分为两种:
1.静态初始化代码块
2.非静态代码块
二者语法上的区别是有无static修饰。具体用法区别暂时不做区分。
了解了构造方法和初始化块功能,那么问题来了,同样是为对象进行初始化,他们的先后顺序是怎么样的呢?我们举一个例子来简单了解一下:
public class Fu01 {
//构造方法
public Fu01() {
System.out.println("父类构造方法");
}
//非静态代码块
{
System.out.println("父类非静态代码块");
}
//静态代码块
static {
System.out.println("父类静态代码块");
}
}
public class Test01 extends Fu01{
//构造方法
public Test01() {
System.out.println("子类构造方法");
}
//非静态代码块
{
System.out.println("子类非静态代码块");
}
//静态代码块
static {
System.out.println("子类静态代码块");
}
public static void main(String[] args) {
new Test01();
}
}
代码运行结果:
通过观察结果我们会发现,当我们创建Test01对象的时候,首先调用静态代码块,然后调用父类构造方法,之后再调用非静态代码块,最后调用子类的构造方法。
当然,可能这个例子太简单了,没有属性,没有普通方法,那么我们换一个复杂点的例子:
//创建父类Person
public class Person
{
String name;
int age;
String sex;
public Person()
{ this("zhangsan");
System.out.println("构造器Person()被调用");
sex ="Male";
System.out.println("name="+name+" ,age="+age+" ,sex="+sex);
}
public Person(String theName)
{ this("lisa",20);
System.out.println("构造器Person(String theName)被调用");
this.name = theName;
System.out.println("name="+name+" ,age="+age+" ,sex="+sex);
}
public Person(String theName,int theAge)
{
System.out.println("构造器Person(String theName,int theAge)被调用");
this.name = theName;
this.age = theAge;
System.out.println("name="+name+" ,age="+age+" ,sex="+sex);
}
//初始化块
{
this.name = "Tony Blair";
this.age = 50;
this.sex = "Female";
System.out.println("Person初始化块执行后:name="+this.name
+" ,age="+this.age+" ,sex="+this.sex);
}
}
//创建子类Teacher
public class Teacher extends Person{
String department;//部门
int schoolAge;//教龄
public Teacher()
{
System.out.println("构造器Teacher()被调用");
}
public Teacher(String name)
{
//调用父类中的构造器Person(String theName)
super(name);
System.out.println("构造器Teacher(String name)被调用");
}
public Teacher(int theSchoolAge)
{
this.schoolAge = theSchoolAge;
System.out.println("构造器 Teacher(int theSchoolAge)被调用 schoolAge = "+ schoolAge);
}
public Teacher(String dept,int theSchoolAge)
{
//调用本类中重载的构造器Teacher(int theSchoolAge)
this(theSchoolAge);
department = dept;
System.out.println("构造器 Teacher(String dept,int theSchoolAge)被调用 department = "+ dept);
}
//初始化块
{
this.department = "教务部";
System.out.println("Teacher初始化块执行后:name="+this.name
+" ,age="+this.age+" ,sex="+this.sex+",department ="+this.department);
}
}
//创建测试类TestInit
public class TestInit
{
public static void main(String[] args)
{
System.out.println("------------------------------------");
Person t1 = new Teacher();
System.out.println("");
System.out.println("------------------------------------");
Person t2 = new Teacher("Tom");
System.out.println("");
System.out.println("------------------------------------");
Person t3 = new Teacher("财务部",20);
}
}
代码有点多,可以自行复制粘贴运行,这里我直接上内存图进行分析:
构造方法压栈运行,最上面的先被调用,最下面的最后被调用。而初始化块是再调用构造方法之前就运行了。
当然,我们也可以用V型图进行分析:
实线表示创建对象的调用过程,虚线表示构造方法压栈的过程。
本文地址:https://blog.csdn.net/qq_41841247/article/details/107091272