1.思考下列代码的执行过程:
public class TestSingleObject { private int cnt = 1; //成员变量 //构造块 { cnt = 2; } // 构造方法 public TestSingleObject() { cnt = 3; } public static void main(String[] args) { TestSingleObject tso = new TestSingleObject(); System.out.println("tso.cnt = "+tso.cnt); } }
打印结果是: 3
执行过程:
- main()方法是程序的入口,进行类的加载
- new TestSingObject();
先对实例变量根据数据类型进行默认初始化赋值 --- int cnt =0;
然后执行 private int cnt = 1; ---- cnt = 1;
然后执行 构造块 {cnt=2;} ----cnt = 2;
最后执行 构造方法 -----cnt =3;
-执行system...("cnt") ------打印出结果到控制台:tso.cnt = 3
重点: 构造块{ } 的执行顺序优于 构造方法
2.在理解以上内容的基础上,加入 static静态相关的代码看看:
public class Dad { public Dad() { System.out.println("Dad类中的构造方法Dad(){}"); }
{
System.out.println("Dad类中的构造块{}");
}
static { System.out.println("Dad类中的静态构造块static{}"); } public static void main(String[] args) { Dad dad = new Dad(); } }
执行结果:
Dad类中的静态构造块static{}
Dad类中的构造块{}
Dad类中的构造方法Dad(){}
执行顺序:
-程序运行,即启动jvm虚拟机,进行 Dad.class类文件的加载
-static修饰的变量和方法 在类加载时期进行,其中static{ }静态构造块只会执行一次
执行 static { System.out.println("Dad类中的静态构造块static{}"); }
-mian()方法是程序的入口,执行 Dad dad = new Dad(); 创建对象,先给成员属性赋对应属于类型的默认值。再执行构造块、最后执行构造方法
- 执行 { System.out.println("Dad类中的构造块{}"); }
-执行 Dad() { System.out.println("Dad类中的构造方法Dad(){}"); }
3.再加入继承 方面的知识 试一试
public class Dad { //父类 { System.out.println("Dad类中的构造块{}"); } public Dad() { System.out.println("Dad类中的构造方法Dad(){}"); } static { System.out.println("Dad类中的静态构造块static{}"); } }
public class Son extends Dad { // 子类继承父类 { System.out.println("Son类中的构造块{}"); } public Son() { System.out.println("Son类中的构造方法Son(){}"); } static { System.out.println("Son类中的静态构造块static{}"); } }
public class Test { //测试代码 public static void main(String[] args) { Son s = new Son(); // 创建子类对象 } }
控制台结果
Dad类中的静态构造块static{} Son类中的静态构造块static{} Dad类中的构造块{} Dad类中的构造方法Dad(){} Son类中的构造块{} Son类中的构造方法Son(){}
执行顺序:
-程序运行,jvm虚拟机启动,类加载时期:
先执行父类的静态构造块,
再执行子类的静态构造块,
-main()方法,程序的入口,执行 Son s = new Son(); // 创建子类对象
先执行 父类的构造块,
再执行 父类的构造方法,
然后才执行 子类的构造块,
执行子类的构造方法,
重点:static通常用来修饰属性和方法,被static修饰的属性和方法都隶属于 类层级(区别于对象层级),类层级的东西随着 类的加载而加载。
最后分析一道阿里面试题:
public class Text { // 1.程序运行,启动jvm虚拟机,进入类加载时期 public static int k = 0 ; public static Text t1 = new Text("t1") ; public static Text t2 = new Text("t2") ; public static int i = print("i") ; public static int n =99 ; public int j = print("j") ; { print("构造块"); } static { print("静态块"); } public Text(String str){ System.out.println((++k)+":"+str+" i="+i+" n="+n) ; ++i;++n ; } public static int print(String str){ System.out.println((++k)+":"+str+" i="+i+" n="+n) ; ++n; return ++i ; } public static void main (String args[]){ Text t = new Text("init") ; } }
结果
1:j i=0 n=0
2:构造块 i=1 n=1
3:t1 i=2 n=2
4:j i=3 n=3
5:构造块 i=4 n=4
6:t2 i=5 n=5
7:i i=6 n=6
8:静态块 i=7 n=99
9:j i=8 n=100
10:构造块 i=9 n=101
11:init i=10 n=102