类的加载

当一个程序使用某一个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化三个步骤来实现对这个类的初始化。

  • 加载
    就是指将该类的 .class文件读入内存中,并为之创建一个Class对象( java.lang.class对象 )。这个Class对象就是用来表示 .class文件内容的东西。(.class文件内容一般包括成员变量、构造方法、成员方法),任何类被使用时,系统都会建立一个Class对象。 
  • 连接
    验证 是否有正确的内部结构,并和其他类协调一致
    准备 负责为类的静态成员分配内存,并设置默认初始值(静态是随着类的加载而加载的,静态内部类只有在被调用时,才会被加载
    public class Test {
        static {
            System.out.println("外部类的输出。");
        }
    
        //静态内部类
        static class StaticInner {
            static {
                System.out.println("内部类的输出。");
            }
    
            static void staticInnerMethod() {
                System.out.println("内部静态方法的输出。");
            }
        }
    
        public static void main(String[] args) {
            Test outer = new Test();     //这里内部类不会被加载
             System.out.println("------------------分割线------------------");
            Test.StaticInner.staticInnerMethod();      //调用内部类的静态方法
        }
    }  
    运行结果:
    Java Class类与反射机制学习笔记(一)-LMLPHP
  • 解析 将类的二进制数据中的符号引用替换为直接引用
    (关于验证、准备、解析更加详细过程见JAVA虚拟机(JVM)——类加载的过程(加载、验证、准备、解析、初始化))
  • 初始化
    类的初始化阶段,虚拟机负责对类进行初始化,主要就是对类变量进行初始化(包括静态属性、静态初始化块)。类初始化之前,先要进行父类初始化, 因为子类可能会用到父类的东西)。在Java类中对类变量指定初始值有两种方式: 
    方式一:声明类变量时指定初始值;
    方式二:使用静态初始化块为类变量指定初始值。在一个类中,如果希望先执行类的初始化动作,可以使用static定义一个静态区域。当这个类被使用时,首先执行static块中的程序,并且只会执行一次。
class Example_A{
	public static int a = 1;//声明变量时指定初始值
	public static int b;//默认值
	public static String str1 = "Hello";//声明变量时指定初始值
	public static String str2;//默认值

	public Example_A(){
		a = 9;
		System.out.println("\n构造函数中\n a的值:" + a);
		System.out.println("b的值:" + b);
		System.out.println("str1的值:" + str1);
		System.out.println("str2的值:" + str2);
	}

	static{//静态域
		System.out.println("执行静态域中的内容:");
		System.out.println("静态域中未改变前, a的值"+ a);
		a = 5;
		System.out.println("静态域中改变后, a的值"+a);
	}
}
public class Test {
	public static void main(String[] args){
		Example_A e1 = new Example_A();
		System.out.println("---------------分割线---------------");
		Example_A e2 = new Example_A();
	}
}

运行结果:srh fbcx 

Java Class类与反射机制学习笔记(一)-LMLPHP

分析:从运行结果我们可以看出,Example_A对象的初始化,首先执行的是static域中的内容,并且这个域只被执行一次。

类的加载时机

类的加载器

 java反射

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制, 在java.lang.reflect包中提供了对该功能的支持。要想解剖一个类,必须先要获取到该类的字节码文件对象而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

 

10-03 10:57