• Class.forName() 与 ClassLoader.loadClass() 的区别


    Class.forName() 与 ClassLoader.loadClass() 的区别

    说明

    1. @author JellyfishMIX - github / blog.jellyfishmix.com
    2. LICENSE GPL-2.0

    介绍

    Class.forName() 与 ClassLoader.loadClass() 这两种方式可以动态加载一个类,区别是:

    1. Class.forName() 的方式加载类时,默认会执行类的初始化。
    2. ClassLoader.loadClass() 的方式加载类时,类不会被初始化,只有显式调用加载的类时才会进行初始化。采用 ClassLoader 进行懒加载,不会调用类的 static 代码块,实现延迟加载。

    demo 演示

    demo 演示上述介绍。

    ClassLoadTest

    public class ClassLoadTest {
        public static void main(String[] args) throws ClassNotFoundException {
            System.out.println("Class.forName 方式加载类--->start");
            Class.forName("classtest.classloader.MyClassForName").getClass();
            System.out.println("Class.forName 方式加载类--->end");
    
            System.out.println("ClassLoader 方式加载类--->start");
            Class<?> bClass = ClassLoader.getSystemClassLoader().loadClass("classtest.classloader.MyClassLoader");
            System.out.println("ClassLoader 方式加载类--->end");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    MyClassForName

    public class MyClassForName {
        static {
            System.out.println("MyClassForName static method execute");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    MyClassLoader

    public class MyClassLoader {
        static {
            System.out.println("MyClassLoader static method execute");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行结果

    运行结果符合预期。

    Class.forName 方式加载类--->start
    MyClassForName static method execute
    Class.forName 方式加载类--->end
    ClassLoader 方式加载类--->start
    ClassLoader 方式加载类--->end
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Class.forName()

    1. 将一个类加载到内存中。
    2. 类默认会被初始化(initialize 这个参数传的是 true),执行内部的静态块代码和保证静态属性被初始化。
    3. 默认会使用当前的 ClassLoader 来加载指定的类。

    ClassLoader.loadClass()

    ClassLoader 的双亲委派模型就不提了。

    1. ClassLoader.loadClass() 的方式加载类时,类不会被初始化,只有显式调用加载的类时才会进行初始化。
    2. 将一个 java 类加载到内存中,类不会被初始化,只有显式使用加载的类时才会进行初始化。因为虚拟机规范规定了,当遇到 new, getstatic, putstatic, invokestatic 这 4 条字节码指令时,如果没有进行过初始化则需要先触发初始化。
    3. 采用 ClassLoader 进行懒加载,不会调用类的 static 代码块,实现延迟加载。

    类的显示使用

    当一个类被显示使用时,JVM 会对其进行初始化,如下六种情况为显示使用:

    1. 当创建某个类的新实例时(如通过 new 或反射,克隆,反序列化等)。
    2. 当调用某个类的静态方法时。
    3. 当使用某个类或接口的静态字段时。
    4. 当调用某些反射方法时,比如类 Class 中的方法,或者 java.lang.reflect 中的类的方法时。
    5. 当初始化某个子类时。
    6. 当 JVM 启动某个被标明为启动类的类(即包含 main 方法的那个类)。
  • 相关阅读:
    C++ 【模板和string模拟实现】
    Opencv Python图像处理笔记一:图像、窗口基本操作
    C++-继承-单继承-多继承-虚函数-内存结构分析-类分析-无源码-逆向分析(三)
    Ansible概述和模块解释
    linux 内核中的pid和前缀树
    Google SGE 正在添加人工智能图像生成器,现已推出:从搜索中的生成式 AI 中获取灵感的新方法
    android逆向工程反编译指南(详细教程)
    Python对json文件的读取和处理
    win10-wsl安装卸载以及软件安装
    HTML标签详解 HTML5+CSS3+移动web 前端开发入门笔记(四)
  • 原文地址:https://blog.csdn.net/weixin_43735348/article/details/127580982