Class.forName()和ClassLoader.loadClass()有何区别

有人问了关于Class.forName()和ClassLoader.loadClass()有何区别的问题,觉得很有意思,便翻了下Class和ClassLoader相关的源码,其中Class源码中关于forName()的方法如下所示:

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

可以看到它返回调用的是本地方法,看不到实现代码::

    private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class<?> caller)
        throws ClassNotFoundException;

但不影响我们从它的形参处猜测这个本地方法想做的是什么,首先name即Class类的全限定类名,initialize为是否初始化标识默认为(true),loader:采用哪个类加载器,caller这个暂时不是很确定到底是什么,默认实现中构造了一个这样的caller对象:

        Class<?> caller = Reflection.getCallerClass();

似乎和反射有关,它调用的也是一个不建议使用的本地方法,从名字猜估计是采用什么类作为调用者。
虽然不是完全能看出具体做了些什么,但大体可以猜出,这个forName方法涉及到了是否将类进行加载。默认对该类进行加载。

下面来看ClassLoader.loadClass(),默认的调用方法是:

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

再来看loadClass的方法,省略一些判断类是否已经被加载的流程,大体逻辑如下:

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 (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

这样子就很明了了,resolve为解析的意思,若传来的boolean为true,则对该类进行解析后返回该类的Class对象。默认为false,则不对该类进行解析。直接返回Class对象。
如果对resolveClass()方法比较好奇的话下面贴出这个方法的源码:

    /**
     * Links the specified class.  This (misleadingly named) method may be
     * used by a class loader to link a class.  If the class <tt>c</tt> has
     * already been linked, then this method simply returns. Otherwise, the
     * class is linked as described in the "Execution" chapter of
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @param  c
     *         The class to link
     *
     * @throws  NullPointerException
     *          If <tt>c</tt> is <tt>null</tt>.
     *
     * @see  #defineClass(String, byte[], int, int)
     */
    protected final void resolveClass(Class<?> c) {
        resolveClass0(c);
    }

    private native void resolveClass0(Class<?> c);
    

可以看出这个也是调用了一个本地方法,从注释可以大概的看出它的作用,连接特定的类。
连接这个词加上解析这个词,联想到了类加载机制的三个流程,加载->连接->初始化,中的连接。因为其中连接分为:校验,准备,解析三个流程,包含解析。
所以推测,Class.forName()涉及到了类的加载;而ClassLoader.loadClass()最多只达到了类加载机制中连接阶段的最后一步:解析;此时仅对类中的静态变量赋了JVM默认的初始值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值