对象初始化过程细节
1.创建对象过程
1 static{ 2 静态代码块中的执行语句 3 } 4 5 特点:随着类的加载而执行,只执行一次并优先于主函数。 用于给类进行初始化。 6 7 Persong p = new Person("XX",XX); 8 9 这句话执行了: 10 <1> 因为new用到了Person.class,所以会先找到Persong.class文件并加载到内存中 11 <2> 执行该类中的static代码块,如果有的话,给Person.class类进行初始化 12 <3> 在堆内存中开辟空间,分配内存地址 13 <4> 在堆内存中建立对象特有属性,并进行默认初始化 14 <5> 对属性进行初始化 15 <6> 对对象进行构造代码块初始化 16 <7> 对对象进行对应的构造函数初始化 17 <8> 将内存地址赋给栈内存中的p变量 18
2.父子间对象初始化过程
1 对象的初始化顺序: 2 3 1.首先执行父类静态的内容,父类静态的内容执行完毕后; 4 2.接着去执行子类的静态的内容,当子类的静态内容执行完毕之后; 5 3.再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕; 6 4.接着执行父类的构造方法,父类的构造方法执行完毕之后; 7 5.它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块,子类的非静态代码块执行完毕; 8 6.去执行子类的构造方法。 9 10 总之一句话,静态代码块内容先执行,接着执行父类非静态代码块和构造方法, 11 然后执行子类非静态代码块和构造方法。 12 13 注意:子类的构造方法,不管这个构造方法带不带参数,默认的它都会先去寻找父类的不带参数的构造方法。 14 如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过。 15
代码演示:
1 class Father 2 { 3 int nonFatherStaticVar = nonFatherStaticShow();//父类非静态变量 4 static int father = FatherStaticShow();//父类静态变量 5 static //父类静态代码块 6 { 7 System.out.println("父亲的static代码块运行了"); 8 } 9 public int nonFatherStaticShow(){ 10 System.out.println("父类非静态变量初始化"); 11 return 1; 12 } 13 public static int FatherStaticShow(){ 14 System.out.println("父类静态变量初始化"); 15 return 2; 16 } 17 public Father()//父类构造方法 18 { 19 System.out.println("父亲的构造函数运行了"); 20 } 21 static void show(){ 22 System.out.println("父亲普通方法运行了"); 23 } 24 25 } 26 class Son extends Father 27 { 28 int nonSonStaticVar = nonSonStaticShow();//子类非静态变量 29 static int son = SonStaticShow();//子类静态变量 30 static //子类静态代码块 31 { 32 System.out.println("子类的static代码块运行了"); 33 } 34 public int nonSonStaticShow(){ 35 System.out.println("子类非静态变量初始化"); 36 return 1; 37 } 38 public static int SonStaticShow(){ 39 System.out.println("子类静态变量初始化"); 40 return 2; 41 } 42 public Son()//父类构造方法 43 { 44 System.out.println("子类的构造函数运行了"); 45 } 46 47 } 48 49 public class InitDemo 50 { 51 public static void main(String[] args) 52 { 53 Son son = new Son(); 54 son.show(); 55 } 56 } 57 58 /* 59 继承中,父子类间的初始化顺序: 60 61 1、父类的静态代码块和静态变量初始化 62 2、子类静态代码块和静态变量初始化 63 3、父类非静态变量初始化 64 4、父类构造函数运行 65 5、子类非静态变量初始化 66 6、子类的构造函数运行 67 */
3.静态代码块不是在类加载时被调用的,而是第一个实例对象被创建时才执行的
1 /* 2 需求:测试构造代码块、静态构造代码块的执行顺序。 3 */ 4 5 class StaticCode1 6 { 7 static 8 { 9 System.out.println("StaticCode1——————静态代码块"); 10 } 11 { 12 System.out.println("StaticCode1————————代码块"); 13 } 14 } 15 16 class StaticCode 17 { 18 static 19 { 20 System.out.println("3。StaticCode*************静态代码块——————"); 21 } 22 { 23 System.out.println("StaticCode************代码块————————"); 24 } 25 } 26 27 class StaticCodeDemo 28 { 29 static 30 { 31 System.out.println("1。StaticCodeDemo静态代码块1"); 32 } 33 { 34 System.out.println("StaticCodeDemo代码块"); 35 } 36 public static void main(String[] args) 37 { 38 //连续创建两个StaticCode类的对象,静态代码块之执行一次,非静态代码块执行两次 39 new StaticCode(); 40 new StaticCode(); 41 42 //同一个类中有多个静态代码块,按由上到下顺序执行 43 new StaticCodeDemo(); 44 45 //StaticCode1类已经加载,但是代码块却没有运行; 46 StaticCode1 code1=null; 47 StaticCode1 code12; 48 49 System.out.println("over"); 50 } 51 static 52 { 53 System.out.println("2。StaticCodeDemo静态代码块2"); 54 } 55 }
程序的运行是:先创建main函数所在类的对象然后才找到main函数执行。
by hacket