反射-类的加载

类的加载

类的加载过程

  • 类的装载(loading)

将类的.class文件读入内存,并位置创建一个java.lang.Class对象。此过程由类加载器完成

  • 链接(linking)

    • 验证(Verify):确认读取的文件是合规的文件
    • 准备(Prepare):为类变量(static)分配内存和赋初值
    • 解析(Res olve):将常量池内的符号引用(常量名)替换为直接引用(地址)的过程
  • 初始化(initialization)

执行类构造器<clinit>()的过程,此方法是由编译器自动收集所有类变量的赋值动作和静态代码块中的语句合并产生的


类加载器的分类

  • 启动类装载器(Bootstrap ClassLoader):加载核心库,使用C/C++语言编写
  • 继承于ClassLoader
    • 扩展类装载器(Exension ClassLoader):加载jre/lib库中的除核心库外的扩展库
    • 应用程序类装载器(ApplicationClassLoader)/系统类加载器(SystemClassLoader):我们自定义的类,默认能使用的类加载器
    • 用户自定义类装载器

使用自定义加载器加载IO流*

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class Test {
    public static void main(String[] args) throws IOException {
        //新建properties集合
        Properties properties = new Properties();
        //使用自定义加载器从文件中加载IO流
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("info.properties");
        properties.load(is);
    } 
}

注:使用类加载器读取文件时,相对路经是在module文件夹下的src文件夹下

而使用File流读取文件的相对目录则是在module根目录下


类加载器加载文件的使用方式

this.getClass()  // getClass() 返回:表示此对象的运行时类的Class对象。
    .getClassLoader()   // 返回:装入此对象表示的类或接口的类装入器。
    .getResourceAsStream("process/process.zip");


this.getClass()  // getClass() 返回:表示此对象的运行时类的Class对象
    .getResourceAsStream("process/process.zip");  

//使用ClassLoader静态类中的静态方法获取当前类加载器
ClassLoader.getSystemClassLoader().getResourceAsStream("process/process.zip");
  • this.getClass().getClassLoader().getResourceAsStream("process/process.zip"): 这种方式使用类加载器(ClassLoader)来加载资源文件。类加载器是用于加载类的机制,并且每个类加载器都有自己的类加载路径。getResourceAsStream方法的路径是相对于类加载器的根路径。因此,"process/process.zip" 这个路径将相对于类加载器的根路径来定位资源文件。

    • 在一些情况下,特别是当使用不同的类加载器(例如自定义类加载器)加载类时,this.getClass().getClassLoader().getResourceAsStream("process/process.zip") 可能更可靠,因为它直接使用类加载器的路径,不受当前类的位置的影响。
  • this.getClass().getResourceAsStream("process/process.zip"): 这种方式使用当前类的类加载器来加载资源文件。getResourceAsStream方法的路径是相对于当前类所在的包路径(package path)。换句话说,它会在当前类的包路径下寻找资源文件。

    • 这种方式适用于当前类和资源文件在同一个包路径下的情况。如果资源文件与当前类在不同的包路径下,或者资源文件位于类加载器的根路径(Classpath根目录)下,这种方式可能会失败,因为它是相对于当前类所在的包路径来定位资源文件。
  • ClassLoader.getSystemClassLoader().getResourceAsStream("process/process.zip");:这种方式和第二种方式相同,区别是使用了静态类和静态方法,路径也是包路径