类加载顺序

我会带着你远行 2022-05-10 09:50 548阅读 0赞

目录

一、类加载做了哪些事?

二、类加载的顺序

三、一个具体说明的例子

四、类加载前和加载后的执行顺序(转自http://blog.csdn.net/mrzhoug/article/details/51581994)


一、类加载做了哪些事?

之前没有进行类加载
1.类加载,同时初始化类中静态的属性(赋默认值)
2.执行静态代码块
3.分配内存空间,同时初始化非静态的属性(赋默认值)
4.如果声明属性的同时有显示的赋值,那么进行显示赋值把默认值覆盖
5.执行匿名代码块
6.执行构造器
7.返回内存地址

二、类加载的顺序

1.static 变量
2.static 代码块
3.成员变量
4.匿名块
5.构造器
ps:先加载父类,再加载子类;

三、一个具体说明的例子

其中D继承C,C继承B,E,F是单独的类,主方法在ExaminationDemo 中。

  1. public class ExaminationDemo {
  2. public static void main(String[] args) {
  3. System.out.println("1运行 ExaminationDemo 中的 main 函数, 创建 D 类实例");
  4. new D();
  5. }
  6. }
  7. class E {
  8. // E的构造器
  9. E() {
  10. System.out.println("8执行 E 的构造函数");
  11. }
  12. // E的普通成员方法
  13. public void funcOfE() {
  14. System.out.println("12执行 E 的函数");
  15. }
  16. }
  17. class F {
  18. // F的构造器
  19. F() {
  20. System.out.println("2执行 F 的构造函数");
  21. }
  22. // F的普通成员方法
  23. public void funcOfF() {
  24. System.out.println("4执行 F 的函数");
  25. }
  26. }
  27. class B {
  28. //new了一个E对象
  29. E e = new E();
  30. //B的静态成员变量
  31. static F f = new F();
  32. //B的普通成员变量
  33. public String sb = getSb();
  34. //B的静态代码块
  35. static {
  36. System.out.println("3执行 B 类的 static 块(B 包含 E 类的成员 变量,包含静态 F 类成员变量)");
  37. f.funcOfF();
  38. }
  39. //B的匿名代码块
  40. {
  41. System.out.println("10执行 B 实例的普通初始化块");
  42. }
  43. //B的构造器
  44. B() {
  45. System.out.println("11执行 B 类的构造函数(B 包含 E 类的成员变 量,包含静态 F 类成员变量)");
  46. }
  47. //B的普通成员方法
  48. public String getSb() {
  49. System.out.println("9初始化 B 的实例成员变量 sb");
  50. return "sb";
  51. }
  52. }
  53. class C extends B {
  54. // C的静态代码块
  55. static {
  56. System.out.println("5执行 C 的 static 块(C 继承 B)");
  57. }
  58. // C的匿名代码块
  59. {
  60. System.out.println("13执行 C 的普通初始化块");
  61. }
  62. // C的构造器
  63. C() {
  64. System.out.println("14执行 C 的构造函数(C 继承 B)");
  65. }
  66. }
  67. class D extends C {
  68. // D的静态成员变量
  69. public String sd1 = getSd1();
  70. // D的普通成员变量
  71. public static String sd = getSd();
  72. // D的静态代码块
  73. static {
  74. System.out.println("7执行 D 的 static 块(D 继承 C)");
  75. }
  76. // D的匿名代码块
  77. {
  78. System.out.println("16执行 D 实例的普通初始化块");
  79. }
  80. // D的构造器
  81. D() {
  82. System.out.println("17执行 D 的构造函数(D 继承 C);父类 B 的实 例成员变量 sb 的值为:" + sb + ";本类 D 的 static 成员变量 sd 的值为:" + sd
  83. + "; 本类 D 的实例成员变量 sd1 的值是:" + sd1);
  84. }
  85. // D的静态成员方法(调用时才加载)
  86. static public String getSd() {
  87. System.out.println("6初始化 D 的 static 成员变量 sd");
  88. return "sd";
  89. }
  90. // D的普通成员方法
  91. public String getSd1() {
  92. System.out.println("15初始化 D 的实例成员变量 sd1");
  93. return "sd1";
  94. }
  95. }

从上面的代码我们可以看出,加载主方法时,先执行了输出语句,然后是new D(),由此进行加载顺序的分析。

执行结果如下:

  1. /*
  2. * 1运行 ExaminationDemo 中的 main 函数, 创建 D 类实例
  3. * 2执行 F 的构造函数
  4. * 3执行 B 类的 static 块(B 包含 E类的成员 变量,包含静态 F 类成员变量)
  5. * 4执行 F 的函数
  6. * 5执行 C 的 static 块(C 继承 B)
  7. * 6初始化 D 的 static 成员变量sd
  8. * 7执行 D 的 static 块(D 继承 C)
  9. * 8执行 E 的构造函数
  10. * 9初始化 B 的实例成员变量 sb
  11. * 10执行 B 实例的普通初始化块
  12. * 11执行 B 类的构造函数(B 包含 E 类的成员变 量,包含静态 F 类成员变量)
  13. * 13执行 C 的普通初始化块
  14. * 14执行 C 的构造函数(C 继承B)
  15. * 15初始化 D 的实例成员变量 sd1
  16. * 16执行 D 实例的普通初始化块
  17. * 17执行 D 的构造函数(D 继承 C);父类 B 的实 例成员变量 sb的值为:sb;本类 D 的 static 成员变量 sd 的值为:sd; 本类 D 的实例成员变量 sd1 的值是:sd1
  18. */

这个结果是怎么来的,看下图:

70

总体上还是按照二的加载顺序来的,需要注意的是,当遇到子父类时,加载顺序是:

父类的静态成员变量,静态代码块——>子类的静态成员变量,静态代码块——>父类的普通成员变量,匿名代码块,构造器

——>子类的普通成员变量,匿名代码块,构造器

静态变量,和静态代码块的顺序先后,主要看谁先写,先写的先加载

new对象和成员变量的顺序,谁写在前面就先加载谁(我理解的是两者都属于成员变量

成员方法不调用就不加载

而,当成员变量是方法时,就要调用该方法。

无论是静态成员方法,还是普通成员方法,只有在调用时才被加载

四、类加载前和加载后的执行顺序(转自http://blog.csdn.net/mrzhoug/article/details/51581994)

如果类还没有被加载:
1、先执行父类的静态代码块和静态变量初始化,并且静态代码块和静态变量的执行顺序只跟代码中出现的顺序有关。
2、执行子类的静态代码块和静态变量初始化。
3、执行父类的实例变量初始化
4、执行父类的构造函数
5、执行子类的实例变量初始化
6、执行子类的构造函数

如果类已经被加载:
则静态代码块和静态变量就不用重复执行,再创建类对象时,只执行与实例相关的变量初始化和构造方法。

发表评论

表情:
评论列表 (有 0 条评论,548人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java顺序

    在java中类的加载、初始化都是在程序运行期完成的,虽然会稍微增加开销,但是却很大的增加了灵活性,我们可用在运行期间动态的去网络或其他地方加载一个二进制流来作为程序代码的一部分

    相关 顺序

    1、父类的静态变量 2、父类的静态代码块 3、子类的静态变量 4、子类的静态代码块 5、父类的非静态变量 6、父类的非静态代码块 7、父类的构造方法

    相关 Java顺序

    Java初始化顺序 1在new B一个实例时首先要进行类的装载。(类只有在使用New调用创建的时候才会被java类装载器装入) 2,在装载类时,先装载父类A,再装载子类

    相关 顺序

    目录 一、类加载做了哪些事? 二、类加载的顺序 三、一个具体说明的例子 四、类加载前和加载后的执行顺序(转自http://blog.csdn.net/mrzhoug/a