Java必备知识之反射

126 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

1. 反射-类的加载

1.1 类的加载概述

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

(1) 加载
就是指将class文件读入内存,并为之创建一个Class对象;
任何类被使用时系统都会建立一个Class对象。

(2)连接
a. 验证: 是否有正确的内部结构,并和其他类协调一致;
b. 准备: 负责为类的静态成员分配内存,并设置默认初始化值;
c. 解析:把类中的符号引用转换为直接引用。

(3) 初始化
a. main方法所在的类在加线时,直接就先初始化;
b. new一个类的对象,一定会先完成类的初始化;
c. 调用该类的静态变量(final的常量除外)和静态方法;
d. 使用java.lang.reflect包的方法对类进行反射调用;
e. 当初始化一个类,如果其父类没有被初始化,则先会初始化他的父类。

1.2 类的加载时机

a. 创建类的实例;
b. 访问类的静态变量,或者为静态变量赋值;
c. 调用类的静态方法;
d. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象;
f. 初始化某个类的子类;
e. 直接使用java.exe命令来运行某个主类。

2. 反射-类加载器

2.1 类加载器的概述

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

2.2 类加载器的分类

(1) Bootstrap ClassLoader 根类加载器
(2) Extension ClassLoader 扩展类加载器
(3) Sysetm ClassLoader 系统类加载器

2.3 类加载器的作用

(1) Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载,比如System,String等,在JDK中JRE的lib目录下rt.jar文件中。

(2) Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载,在JDK中JRE的lib目录下ext目录。

(3) Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath 环境变量所指定的jar包和类路径。

3. 反射-反射概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个 类的所有属性和方法。对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

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

4. 反射-获取class对象

4.1 获取class对象三种方式

(1) Object类的getClass()方法
(2) 静态属性class
(3) Class类中静态方法forName()

4.2 获取class对象三种方式代码示例

getClass()方法

import  java.util.Date;
public class test {
    public static void main(String[] args) {
        Date date=new Date();
        System.out.println(date.getClass());
    }
}

类的静态属性class

import java.util.Date;
 
public class test {
    public static void main(String[] args) throws  Exception{
        System.out.println(Date.class);
 
    }
}

Class.forName()方法

import  java.lang.Class;
public class test {
    public static void main(String[] args) throws  Exception{
        Class<?> date =Class.forName("java.util.Date");
        System.out.println(date);
 
    }
}

除了getClass()方法会实例化对象之外,其他的两种不会产生实例化对象。

5. 反射-通过反射实例化对象

通过反射实例化对象方法:对象.newInstance()
newInstance()方法内部实际上调用了无参数构造方法,必须保证无参构造存在才可以

import  java.lang.Class;
import java.util.Date;
 
public class test {
    public static void main(String[] args) throws Exception{
        //通过反射机制,获取Class,通过Class来实例化对象
        Class<?>  cl=Class.forName("java.util.Date");
        //newInstance() 这个方法会调用Date这个类的无参数构造方法,完成对象的创建。
        // 重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
        Object object=cl.newInstance();
        System.out.println(object);
 
    }
}