首页 > 代码库 > Java---类加载机制,构造方法,静态变量,父类,变量加载顺序
Java---类加载机制,构造方法,静态变量,父类,变量加载顺序
直接上代码:
代码1:
public class ConstroctTest { private static ConstroctTest test = new ConstroctTest(); //静态变量sta1 未赋予初始值 public static int sta1; //静态变量sta1 赋予初始值20 public static int sta2 = 20; //构造方法中对于静态变量赋值 private ConstroctTest() { sta1 ++ ; sta2 ++ ; } public static void main(String[] args) { System.out.println(ConstroctTest.sta1); System.out.println(ConstroctTest.sta2); } }
结果:
1
20
代码2:
public class ConstroctTest { //静态变量sta1 未赋予初始值 public static int sta1; //静态变量sta1 赋予初始值20 public static int sta2 = 20; private static ConstroctTest test = new ConstroctTest(); //构造方法中对于静态变量赋值 private ConstroctTest() { sta1 ++ ; sta2 ++ ; } public static void main(String[] args) { System.out.println(ConstroctTest.sta1); System.out.println(ConstroctTest.sta2); } }
结果:
1
21
结果分析:
1. 按照静态变量的顺序,初始化各静态变量。(给变量赋予默认值)
2. 按照顺序,赋予静态变量的初始值。
3. 以上结果在于:类静态变量的位置,决定着通过构造方法给sta1 与 sta2 赋予的值是否有效。
4. 在代码一中,先对于sta2 执行了 sta2 ++ 操作。而后给sta2 赋予静态变量值。(只因为顺序问题)
代码3:
public class ConstroctTest { //静态变量sta1 未赋予初始值 public static int sta1; //静态变量sta1 赋予初始值20 public static int sta2 = 20; private static ConstroctTest test = new ConstroctTest(); //构造方法中对于静态变量赋值 private ConstroctTest() { System.out.println("123456"); sta1 ++ ; sta2 ++ ; } public static void main(String[] args) { System.out.println(ConstroctTest.sta1); System.out.println(ConstroctTest.sta2); System.out.println(ConstroctTest.sta1); System.out.println(ConstroctTest.sta1); } }
结果:
结果分析:
1. 从结果可以看出,Java的静态变量,只是在类第一次加载,初始化的时候执行。
2. 类变量不依赖类的实例,类变量只在初始化时候在栈内存中被分配一次空间,无论类的实例被创建几次,都不再为类变量分配空间。
3. 可以看出 ,类变量的执行与初始化,与实例对象没有关系。
代码4:
public class Test{ public static void main(String[] args){ Child ch = new Child(); } } class Parent{ static String name1 = "hello"; static{ System.out.println("Parent static block"); } public Parent(){ System.out.println("Parent construct block"); } } class Child extends Parent{ static String name2 = "hello"; static{ System.out.println("Child static block"); } public Child(){ System.out.println("Child construct block"); } }
结果:
结果分析:
1. 明先初始化父类的静态属性在执行自己的静态属性,再是父类的构造方法再是自己的构造方法。
2. 实例化 Child 类。第一要初始化类Child ,因为Child拥有父类(会判断父类是否初始化),类的初始化只有一次。。初始化类(就是按照顺序加载静态变量与静态方法)。
3. 初始化Child后。开始实例化Child ,因为拥有父类,所以调用构造方法之前会调用父类的默认构造方法。
代码5:
public class Animal { private static int k; static{ System.out.println("父类的静态方法"); } { System.out.println("执行父类的构造代码块"); } public Animal(){ System.out.println("执行父类的构造方法"); } public static void main(String[] args) { System.out.println(Animal.k); } }
运行结果:
父类的静态方法
0
结果分析:
1. 构造代码块与构造方法对于类的加载 没有关系。
代码6:
public class Animal { private static int k; { System.out.println("执行父类的构造代码块"); } static{ System.out.println("父类的静态方法"); } public Animal(){ System.out.println("执行父类的构造方法"); } public static void main(String[] args) { Animal animal1 = new Animal(); Animal animal2 = new Animal(); } }
结果:
结果分析:
1. 构造代码块至于构造方法相关,随着构造方法的执行而执行。
代码7:
public class Cat { private static int a; private static int b = 1000; static{ a = 100; b = 200; } public static void main(String[] args) { System.out.println(Cat.a); System.out.println(Cat.b); } }
结果分析:
1. 可以把静代码块中的内容 看做是赋予操作。
2. 当静态代码块在a,b前面。此时输出的结果是100 1000
代码8:
class Animal { { System.out.println("执行父类的构造代码块"); } static{ System.out.println("父类的静态方法"); } public Animal(){ System.out.println("执行父类的构造方法"); } public void A(){ System.out.println("执行父类的A方法"); } } public class Cat extends Animal{ static{ System.out.println("子类的静态方法"); } { System.out.println("执行子类的构造代码块"); } public Cat(){ System.out.println("执行子类的构造方法"); } @Override public void A() { System.out.println("执行子类的A方法"); } public static void main(String[] args) { Cat c = new Cat(); c.A(); } }
通过上面的分析,结果应该很明确了:
3,装载父类A后,完成静态动作(包括静态代码和变量,它们的级别是相同的,安装代码中出现的顺序初始化)
4,装载子类B后,完成静态动作
类装载完成,开始进行实例化
1,在实例化子类B时,先要实例化父类A
2,实例化父类A时,先成员实例化(非静态代码)
3,父类A的构造方法
4,子类B的成员实例化(非静态代码)
5,子类B的构造方法
先初始化父类的静态代码--->初始化子类的静态代码-->初始化父类的非静态代码--->初始化父类构造函数--->初始化子类非静态代码--->初始化子类构造函
Java---类加载机制,构造方法,静态变量,父类,变量加载顺序