类名.class, class.forName(), getClass()区别及ClassLoader.getSystemClassLoader().loadClass()

在反射中,我们经常见到类名.class和Class.forName(),以及getClass(),以及加载类的ClassLoader.getSystemClassLoader().loadClass()方法,下面我们来研究一下他们之间的区别。

什么是class

java在加载类通过类的全限定名获取二进制字节流,将二进制字节流转换成方法区中的运行时数据结构,会在内存中生成Java.lang.Class对象。

每个类都有一个Class对象,该Class对象包含了创建对应类所需的各种信息,在我们编译一个新定义的Java类时会生成一个相应的Class对象(也就是同名的.class文件),程序中需要实例化该类时,就通过该类对应的Class对象来创建该类的实例,不过在此之前需要先将相应的.class文件加载到JVM(Java Virtual Machine, Java虚拟机)中,这个工作由一个称之为ClassLoader的类加载器完成。

类名.class, class.forName(), getClass()区别

  • 1、Class cl=A.class;
    JVM将使用类A的类装载器, 将类A装入内存(前提是:类A还没有装入内存),不对类A做类的初始化工作.返回类A的Class的对象。

  • 2、Class clazz=对象引用obj.getClass();
    返回引用obj运行时真正所指的对象(因为:子对象的引用可能会赋给父对象的引用变量中)所属的类的Class的对象 。

  • 3、Class.forName(类名字符串);
    (注:类名字符串是包名+类名)装入类,并做类的静态初始化,返回Class的对象

    .getClass()是动态的,其余是静态的。

.class和Class.forName()只能返回类内field的默认值,getClass可以返回当前对象中field的最新值

Class.forName() 返回的是一个类,.newInstance() 后才创建一个对象,Class.forName()的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的加载

Class.forName()和ClassLoader.getSystemClassLoader().loadClass的区别

Class.forName(className)源码

 @CallerSensitive
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

第2个boolean参数表示类是否需要初始化, Class.forName(className)默认是需要初始化。

一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化。

ClassLoader.loadClass源码

public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

ClassLoader.getSystemClassLoader().loadClass(className)方法,内部实际调用的方法是 ClassLoader.loadClass(className,false);
第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,由上面介绍可以,

不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行

区别如下

  • Class.forName()会进行初始化
  • ClassLoader.getSystemClassLoader().loadClass不会进行初始化
点赞

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注