特性
一 Java程序的初始化3个原则(优先级依次递减)
-
静态对象(变量) > 非静态对象(变量):静态对象(变量)只是初始化一次,而非静态对象(变量)可以初始化很多次;
-
父类 >子类;
-
按照成员变量的定义顺序进行初始化
二 Java程序的初始化是通过不同的代码块来完成的。那么,类加载的顺序是:
- 父类的静态对象(成员变量)和静态代码块;
- 子类的静态对象(成员变量)和静态代码块;
- 父类非静态对象(成员变量)和非静态代码块;
- 父类构造函数;
- 子类的非静态对象(成员变量)和非静态代码块;
- 子类的构造函数。
三 补充说明
- 静态块:用static声明;JVM加载类的时候执行,仅会执行一次(静态代码块按照声明顺序执行);静态代码块的作用完成类的初始化;
- 构造块:类中直接用{}定义;每一次创建对象的时候执行;
- 执行顺序的优先级:静态块>main()>构造块>构造方法
示例代码
示例代码1
package com.niuke;
public class Test {
public static Test t1 = new Test();
{
System.out.println("111");
}
static{
System.out.println("222");
}
public static void main(String[] args){
Test t2 = new Test();
}
}
111
222
111
1.代码中有两处static代码块
public static Test t1 = new Test();
执行此处的static块会创建一个对象,所以会先执行{}中的方法;在控制台打印“111”。
static{
System.out.println("222");
}
在控制太打印“222”
Test t2 = new Test();
在main()函数中只也创建了一个对象t2,所以也会执行{}中的代码块。
实例代码2
package Test_10;
class Base{
Base(){
System.out.println("基类的构造函数");
}
static{
System.out.println("基类的静态函数");
}
}
public class Test extends Base{
Test(){
System.out.println("Test 类的构造函数");
}
static{
System.out.println("Test类的静态函数");
}
public static void main(String[] args){
Test test = new Test();
}
}
运行结果
基类的静态函数
Test类的静态函数
基类的构造函数
Test 类的构造函数
示例代码3
package Test_10;
//基类
class Base{
//构造函数
Base(){
System.out.println("基类的构造函数");
}
//静态代码块
static{
System.out.println("基类的静态函数");
}
//构造函数块,在new一个对象的时候先于构造函数执行
{
System.out.println("基类的构造函数块");
}
}
//子类
public class Test extends Base{
Test(){
System.out.println("Test 类的构造函数");
}
static{
System.out.println("Test类的静态函数");
}
{
System.out.println("Test类的构造函数块");
}
public static void main(String[] args){
new Test();
System.out.println("//******************");
new Test();
}
}
运行结果:
基类的静态函数
Test类的静态函数
基类的构造函数块
基类的构造函数
Test类的构造函数块
Test 类的构造函数
//******************
基类的构造函数块
基类的构造函数
Test类的构造函数块
Test 类的构造函数
示例代码4
package Test_10;
class X{
Y y = new Y();//父类非静态对象
public X(){
System.out.println("X");
}
}
class Y{
public Y(){//非静态对象
System.out.println("Y");
}
}
class Z extends X{
Y y = new Y();//子类非静态对象
public Z(){
System.out.println("Z");
}
}
public class Test3 {
public static void main(String[] args){
new Z();
}
}
运行结果:
Y
X
Y
Z
- 代码中没有static修饰的代码块和成员变量,main()函数中,new z()时,调用其父类(先加载成员变量 :Y y = new Y() —>调用Y类的构造函数输出“Y”,然后再执行构造函数—>输出“X”)
- 初始化子类Z的普通出成员变量和代码块(先执行 Y y = new Y()---->输出“Y”,然后执行Z类的构造函数---->输出“Z”)