反射概念

类的加载概述和加载时机

类的加载概述

  • 类的加载是指: 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类的初始化.
  • 加载: 指的是将Javac创建的class文件读入内存,并为之创建一个Class对象,任何类被使用时系统都会建立一个Class对象

  • 连接: 包括三个步骤:

  1. 验证 是否有正确的内部结构,并和其它类协调一致.

  2. 准备 负责为类的静态成员分配内存,并设置默认初始化值.

  3. 解析 将类的二进制数据中的符号引用替换为直接引用,比如把常量的引用直接变成值.

  • 初始化: 就是给成员变量赋值: 先默认值(比如int默认值为0)---->然后显式赋值(比如public inta = 10,这个**=**就是显式初始化)---->最后构造方法初始化(带参构造会给成员变量赋值这个都知道哈).

类的加载时机

  • 创建类的实例时,例: Preson p = new Person().

  • 访问类的静态变量,或者为静态变量赋值时

  • 调用类的静态方法

  • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象.

  • 初始化某个类的子类

  • 直接使用java.exe命令来运行某个主类

类加载器的概述和分类

类加载器的概述

  • 负责将.class文件加载到内存中,并为之生成对应的Class对象.

类加载器的分类

  1. Bootstrap ClassLoader: 根类加载器

  2. Extension ClassLoader: 扩展类加载器

  3. System ClassLoader: 系统类加载器

类加载器的作用

  • 根类加载器负责java核心类的加载,比如System,String等,在jre的lib目录下的rt.jar文件中.

  • 扩展类加载器负责jre扩展目录中jar包的加载,在jre的lib目录下的ext目录下.

  • 系统类加载器负责jvm启动时加载来自java命令的class文件比如自定义类,以及classpath环境变量所指定的jar包和类路径

类初始化顺序

  • 只有一个类的话,他的初始化顺序是这样子的
  1. 静态成员变量

  2. 静态代码块,例如: static{System.out.println(“静态代码块”)}

  3. 普通成员变量

  4. 普通代码块(就是静态代码块没有static关键字,直接就是{内容})

  5. main方法

  6. 构造方法

反射

反射概述

  • java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的任意属性和方法,对于任意一个对象,都能够调用它的属性和方法

  • 这种动态获取信息以及动态调用对象的方法和属性的功能称为java的反射机制

  • 要想解剖一个类,必须先要获取到该类的字节码文件(字节码文件就是.class文件)对象,而解剖类使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象

获取Class文件对象的三种方式

  • Object类的getClass()方法,用于判断两个对象是否是同一个字节码文件,重写equals()方法时就有这么一个判断条件,调用格式: 对象名.getClass().

  • 静态属性.class,即Person.class,用于当作静态方法的锁对象,调用格式: 类名.class

  • 注意: 用.class创建Class对象时,不会自动初始化该Class对象(即不会加载静态代码块这些东西),Class的初始化在调用方法或者属性时候才会被执行
  • Class类中静态方法forName(“全类名即包名.类名”),用于读取配置文件,例如我们读取jdbc的配置文件的时候,调用格式: 全类名.forName()
  • 注意: 用这种方法创建成功Class对象后,就会立即对该对象进行初始化,即会马上执行静态代码块这些东西.
  • 注意:
  • 如果一个字段被static final修饰,我们称为’编译时常量’,在编译期就把它的值放到常量池里了,那么如果通过.class创建Class对象的话,由于没有立即对Class对象进行初始化,然后该对象去调用常量也是不会对Class对象进行初始化的,也就是说不会调用static静态代码块这些东西.

  • 三种创建Class对象的方式,如果是针对同一个字节码文件的话,三个对象是相等的,因为一个字节码文件在内存中只会存在一个Class对象

我们写代码经历的不同的阶段以及在不同的阶段获取Class对象的方法如图:
反射概念_第1张图片
案例演示获取Class对象的三种方式以及初始化顺序

	public class Test4 {
	    public static final int a =10;
	
	    static int b = 20;
	
	    public static void main(String[] args) {
	        System.out.println("main函数加载了");
	        Test4 t = new Test4();
	    }
	
	    public static void get() {
	        System.out.println("这是静态方法");
	    }
	    static {
	        System.out.println("静态代码块被加载了");
	    }
	
	    public Test4() {
	        System.out.println("构造方法被加载了");
	    }
	    public int c = 30;
	
	    {
	        System.out.println("代码块加载了!");
	    }
	
	}
	
	class Test{
	    public static void main(String[] args) throws ClassNotFoundException {
	        Class c = Test4.class;
	        Test4 t = new Test4();
	        Class c1 = t.getClass();
	
	        Class c2 = Class.forName("Test4");
	        System.out.println("--------- ");
	        System.out.println(c == c2);//true
	        System.out.println(c1 == c);//true
	        System.out.println(c1 == c2);//true
	
	    }
	}

你可能感兴趣的:(反射概念)