Java笔记(十二)……类中各部分加载顺序及存放位置问题

什么时候会加载类

使用到类中的内容时加载,三种情况:

  • 创建对象:new StaticDemo();
  • 使用类中的静态成员:StaticCode.num = 9;  StaticCode.getNum();
  • 在命令行中运行:java StaticDemo

类所有内容加载顺序及内存中的存储位置

语句分析

Person p = new Person(“Shawn”,20);

  1. 在栈内存中,开辟main函数的空间,建立main函数的变量p。
  2. 加载类文件:因为new要用到Person.class,所以要先从硬盘中找到Person.class类文件,并加载到内存中。
    • 加载类文件时,除了非静态成员变量不会被加载,其他的都会被加载。
    • 静态成员变量(类变量)------>方法区的非静态部分
    • 静态方法------>方法区的静态部分
    • 静态代码块------>方法区的静态部分
    • 构造代码块------>方法区的静态部分
    • 注意:在Person.class文件加载时,静态方法和非静态方法都会被加载到方法区中,只不过要调用非静态方法时需要先实例化一个对象,对象才能调用非静态方法。如果让类中所有的非静态方法都随着对象的实例化而建立一次,那么会大量消耗内存资源,所以才会让所有对象共享这些非静态方法
  3. 执行类中的静态代码块:如果有的话,对 Person.class类进行初始化。
  4. 开辟空间:在堆内存中开辟空间,分配内存地址。
  5. 默认初始化:在堆内存中建立对象的特有属性,并进行默认初始化。
  6. 显式初始化:对属性进行显示初始化。
  7. 构造代码块:执行类中的构造代码块,对对象进行构造代码块初始化。
  8. 构造函数初始化:对对象进行对应的构造函数初始化。
  9. 将内存地址赋值给栈内存中的变量p。

p.setName(“Feng”);

  1. 在栈内存中开辟setName()方法的空间,里面有:对象的引用this,临时变量name
  2. 将p的值赋值给this,this就指向了堆中调用该方法的对象
  3. 将"Feng"赋值给临时变量name
  4. 将临时变量的值赋值给this指向的name

Person.showCountry();

  1. 在栈内存中,开辟showCountry()方法的空间,里面有:类名的引用Person
  2. Person指向方法区中的Person类的静态方法区的地址
  3. 调用静态方法区中的country,并输出
    • 注意:
    • 要想使用类中的成员,必须调用
    • 通过什么调用?
    • 类名,this,super。

静态代码块、构造代码块和构造函数的区别

静态代码块:用于给类初始化,类加载时就会被加载执行,只执行一次。

构造代码块:用于给对象初始化,只要建立对象该部分都会执行,优先于构造函数执行,每个对象只执行一次。

构造函数:给对象的对象初始化,建立对象是,选择相应的构造函数初始化对象

创建对象时,三者被加载执行顺序是:静态代码块--->构造代码块--->构造函数

   1: class Person 
   2: {
   3:     //非静态变量,对象建立时存在于堆中
   4:     private int age = 0;
   5:     //静态变量,类加载时存在于方法区的静态部分
   6:     private static String country = "cn";
   7:     //静态代码块,类加载时,存在于方法区的静态部分
   8:     static
   9:     {
  10:         System.out.println("class load");
  11:     }
  12:     //构造代码块,类加载时,存在于方法区的静态部分
  13:     {
  14:         System.out.println("object load");
  15:     }
  16:  
  17:     Person(int age)
  18:     {
  19:         this.age = age;
  20:     }
  21:  
  22:     //静态方法,类加载时存在于方法区的静态部分
  23:     public static void showCountry()
  24:     {
  25:         System.out.println(country);
  26:     }
  27:     //非静态方法,类加载时存在于方法区的非静态部分
  28:     void print()
  29:     {
  30:         System.out.println(age);
  31:     }
  32: }

总结

类加载

下列被加载:

  • 类变量(静态成员变量)
  • 静态和非静态方法
  • 静态代码块和构造代码块

下列被执行:

  • 类变量的默认初始化和显式初始化
  • 静态代码块

对象加载

下列被加载:

  • 如果类第一次被用到,则先加载上面类的相关内容
  • 非静态成员变量

下列被执行:

  • 非静态成员变量的默认初始化和显式初始化
  • 如果类第一次被用到,则先执行上面类的相关内容
  • 构造代码块
  • 构造函数

存储位置

memory

你可能感兴趣的:(java)