[转载]【java】类的加载和对象的构造(实例化)过程及顺序

【文章转载自】:【java】类的加载和对象的构造(实例化)过程及顺序

1.类的加载

1.1 什么类的加载load?(Node类的加载)

答.从硬盘上找到Node.class,解析该文件内容,生成Node类,把Node类的信息存放在内存的方法区

1.2 什么情况下回触发类的加载?并且该类不在内存中

(1)按需加载(懒加载过程)

          a.实例化该类的一个对象 new Node(1);

          b.使用类的静态属性或者静态方法 Main.merge(…)

          c.用到子类,必须要有父类 new CNode

         d.先加载父类的静态代码块,再加载子类的静态代码块

1.3 其他规则

静态属性的初始化顺序:

按代码的书写顺序,执行

a.静态属性定义时的初始化

b.静态代码

2.代码块

代码块定义:使用“{}”定义的一段代码;

构造代码块是跟着对象的加载而加载的。

2.1 普通代码块

普通代码块:定义在方法中的代码块;


  
  
  1. public class Test1 {
  2. public static void main(String[] args) {
  3. {
  4. //普通代码块
  5. int a= 10;
  6. System.out.println(a);
  7. }
  8. int a= 20;
  9. System.out.println(a);
  10. }
  11. }

2.2 构造块

构造块:定义在类中的代码块(不加修饰符)


  
  
  1. class A{
  2. //定义在类中,不加任意修饰符
  3. {
  4. System.out.println( "A的构造块");
  5. }
  6. //构造方法
  7. public A(){
  8. System.out.println( "A的构造方法");
  9. }
  10. }
  11. public class Test2 {
  12. public static void main(String[] args) {
  13. new A();
  14. new A();
  15. }
  16. }

通过上述代码可以发现:构造块优先于构造方法执行,每产生一个新的对象就调用一次构造块。所以构造块可以进行简单的逻辑操作(在调用构造方法之前)。

2.3 静态代码块

静态代码块:使用static定义的代码块,它是跟着类的加载而加载的。

根据静态代码块所在的类不同又可分为以下两种类型:

1.在非主类中的静态代码块

2.在主类中的静态代码块

2.3.1 在非主类中的静态代码块


  
  
  1. class B{
  2. //构造块
  3. {
  4. System.out.println( "B类的构造块");
  5. }
  6. //代码方法
  7. public B(){
  8. System.out.println( "B类的构造方法");
  9. }
  10. //静态代码块
  11. static {
  12. System.out.println( "B类的静态代码块");
  13. }
  14. }
  15. public class Test3 {
  16. public static void main(String[] args) {
  17. System.out.println( "==============================");
  18. new B();
  19. new B();
  20. System.out.println( "==============================");
  21. }
  22. }

可以发现:

                1.在非主类的静态代码块中,在类加载时执行,优先于构造块执行

                2.无论产生多少实例化对象,静态代码块只执行一次

静态块的主要作用是为static属性进行初始化!

2.3.2 在主类中的静态代码块


  
  
  1. public class Test4 {
  2. //构造块
  3. {
  4. System.out.println( "Test4类的构造块");
  5. }
  6. //构造方法
  7. public Test4(){
  8. System.out.println( "Test4类的构造方法");
  9. }
  10. //静态代码块
  11. static {
  12. System.out.println( "Test4类的静态代码块");
  13. }
  14. public static void main(String[] args) {
  15. System.out.println( "===========================");
  16. new Test4();
  17. new Test4();
  18. System.out.println( "===========================");
  19. }
  20. }

在主类中定义的静态块,优先于主方法(main)执行,在JVM启动时执行,当编译执行时JVM会首先加载主类,此时主类中的静态代码块就会执行。

3.对象的构造/实例化 new Node

3.1 规则

1.优先初始化父类的属性,(和下面的执行顺序相同)

2.按照下面的顺序执行初始化

a.按照代码书写顺序,执行定义时和构造代码块

b.再去执行构造方法

3.静态代码块只在加载时执行一次,先执行父类的静态代码块,再执行子类的静态代码块。

3.2关于执行顺序的问题

1.父类的加载在子类之前

2.父类的构造方法在子类之前调用

3.static属性初始化是在类的加载时执行(按顺序执行)

1)定义时初始化

2)构造代码块时初始化

4.普通属性初始化是在对象的构造时执行(按顺序执行)

1)定义时初始化

2)构造代码块时初始化

3)构造方法时初始化

5.只有用到类,才会加载类


  
  
  1. class Hello{
  2. //构造方法
  3. public Hello(){
  4. System.out.println( "1.Hello父类的构造方法");
  5. }
  6. //非静态代码块
  7. {
  8. System.out.println( "2.Hello父类非静态代码块");
  9. }
  10. //静态代码块
  11. static{
  12. System.out.println( "3.Hello父类静态代码块");
  13. }
  14. }
  15. public class HelloA extends Hello{
  16. public HelloA(){
  17. System.out.println( "4.helloA构造方法");
  18. }
  19. //非静态代码块
  20. {
  21. System.out.println( "5.HelloA非静态代码块");
  22. }
  23. //静态代码块
  24. static{
  25. System.out.println( "6.HelloA静态代码块");
  26. }
  27. public static void main(String[] args) {
  28. System.out.println( "7.---start---");
  29. new HelloA();
  30. new HelloA();
  31. System.out.println( "8.---end---");
  32. }
  33. }

按照上面讲的执行顺序执行:因为先用到了主类HeoolA,所以先加载了静态代码块;

执行结果:


  
  
  1. class Hello1{
  2. //构造方法
  3. public Hello1(){
  4. System.out.println( "1.Hello1父类的构造方法");
  5. }
  6. //非静态代码块
  7. {
  8. System.out.println( "2.Hello1父类非静态代码块");
  9. }
  10. //静态代码块
  11. static{
  12. System.out.println( "3.Hello1父类静态代码块");
  13. }
  14. }
  15. class Hello2 extends Hello1 {
  16. public Hello2() {
  17. System.out.println( "4.hello2构造方法");
  18. }
  19. //非静态代码块
  20. {
  21. System.out.println( "5.Hello2非静态代码块");
  22. }
  23. //静态代码块
  24. static {
  25. System.out.println( "6.Hello2静态代码块");
  26. }
  27. }
  28. public class Test{
  29. public static void main(String[] args) {
  30. System.out.println( "7.---start---");
  31. new Hello2();
  32. new Hello2();
  33. System.out.println( "8.---end---");
  34. }
  35. }

运行结果:

注:代码块的内容参考本文章!!!

发布了5 篇原创文章 · 获赞 0 · 访问量 1178

猜你喜欢

转载自blog.csdn.net/u013310037/article/details/102975677