loadClass和forName的区别

类的加载方式

隐式加载:new
显示加载:loadClass,forName等

在这里插入图片描述

loadClass和forName的区别

让我们直接干进源码!!

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

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

LoadClass主要还是看 ClassLoad类里的loadClass方法,
让我们看看第二个参数 resolve的解释
在这里插入图片描述
意思是是否要 链接 这个类,如果为true会进入到 resolveClass这个方法,然后找到该方法的注释,第一句话就是链接指定的类!
在这里插入图片描述

forName

同样直接干进源码

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

这里看 forName0 的第二个参数 initialize 意为是否初始化。

以上说明:

1.Classloader.loadClass得到的class是还没有链接的,只完成了 上图中的第一步
2.Class.forName得到的class是已经初始化完成的,已经完成到了上图中的第三步

什么?你不相信?好吧,那我们用代码来说话
以Robot为例
若能打印出 静态块里的代码,说明已经完成初始化

public class Robot {


    private String name;

    static {
        System.out.println("Hello Robot");
    }

}
public class LoadDifference {
        public static void main(String[] args){
                ClassLoader cl = Robot.class.getClassLoader();

            }
}

输出
为空
接下来换成forName

public class LoadDifference {
        public static void main(String[] args){
                Class.forName("reflect.Robot");

            }
}

输出在这里插入图片描述
所以很好的证明了以上的结论。

作用?

Class.forName已经初始化,那为什么还要用LoadClass呢?
LoadClass在springIOC中资源加载器获取要读入的资源的时候,即读取一些bean的配置文件的时候,如果是以classPath方式来加载的话就需要使用Classload.loadclass来加载,之所以这样做是和springIOC的lazy-loading(懒加载)有关,springIOC为了加快初始化速度因此大量使用延迟加载技术,而使用ClassLoad不需要执行类中的初始化代码(static)步骤和链接步骤,这样做可以加快加载速度,把类的初始化工作留到实际使用到这个类的时候才去做。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值