构造函数:又叫构造方法,是一种特殊的函数,之所以说他特殊是因为他没有返回值,在创建对象的时候调用。在非构造函数中不可以调用构造函数,构造函数间可以相互调用(通过this关键字)。子类的构造函数也可调用父类的构造方法(通过super关键字)。注意:当构造函数间相互调用时必须在第一行调用!如果没有编写类时没有定义构造函数,那么系统会默认添加一个空参数的构造函数。
————————————————————————————————————————————————
当创建一个类时,如 Student stu = new Student();
jvm到底做了些什么?
1.栈内存分配main中的stu空间。
2.因为new用到了Studetn.class文件,所以会先找到Student.class文件加载到内存中。
3.执行父类静态代码块。(类初始化)
4.执行子类静态代码块。(类初始化)
5.在堆内存中建立对象的特有属性,并进行默认初始化。
6.父类显示初始化。**
7.执行父类构造代码块。
8.执行父类构造函数。
9.子类显示初始化。**
10.执行子类构造代码块。
11.执行子类构造函数。
———————————————————————————————————————
验证代码如下:
class fu
{
other1 o = new other1();
static
{
System.out.println("父类的静态代码块");
}
{
System.out.println("父类的构造代码块");
}
fu()
{
System.out.println("父类的构造函数");
}
}
class other1
{
other1()
{
System.out.println("父类显示初始化");
}
}
class other2
{
other2()
{
System.out.println("子类显示初始化");
}
}
class zi extends fu
{
other2 o = new other2();
static
{
System.out.println("子类的静态代码块");
}
{
System.out.println("子类的构造代码块");
}
zi()
{
System.out.println("子类的构造函数");
}
}
class gouzhao
{
public static void main(String[] args)
{
zi zilei = new zi();
}
}
---------------------------------
运行结果:
父类的静态代码块
子类的静态代码块
父类显示初始化
父类的构造代码块
父类的构造函数
子类显示初始化
子类的构造代码块
子类的构造函数
----------------------------------
class X
{
int xmask = 1;
int mask;
X()
{
mask = xmask;
System.out.println("mask="+mask);//1
method();//调用了可以被子类重载的方法,获取的ymask=0;
//ymask尚未完成显示初始化。
}
void method()
{
System.out.println("父类的method方法,xmask="+xmask);
}
}
class Y extends X
{
int ymask = 2;
Y()
{
mask += ymask;
System.out.println("mask="+mask);//3
method();
}
void method()
{
System.out.println("子类的method方法,ymask="+ymask);
}
}
class Demo4
{
public static void main(String[] args)
{
Y test = new Y();
}
}
---------------------------------
运行结果:
mask=1
子类的method方法,ymask=0
mask=3
子类的method方法,ymask=2
---------------------------------
分析:
子类和父类的构造函数都调用了method方法,
执行的都是子类的method方法,
但是method输出的结果却不一样;
总结:在设计对象构造阶段调用的这些方法必须考虑上面这些因素。
构造函数应该避免调用那些可覆盖的方法,即不是私有的,静态的或final的方法。
如果调用了这些方法,必须在文档中特别说明。
——————————————————————————————————————————————