美文网首页
Class.forName和Classloder.loaderC

Class.forName和Classloder.loaderC

作者: 念䋛 | 来源:发表于2021-07-03 10:51 被阅读0次

示例

public class ClassForNameClassLoaderTest {
    public static String nihao = "nihao";
    static{
        System.out.println ("我是静态代码块");
    }
    {
        System.out.println ("我是非静态代码块");
    }
}
public class ClassLoaderTest {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //执行静态代码块和静态变量的赋值
        Class<ClassForNameClassLoaderTest> aClass = ( Class<ClassForNameClassLoaderTest> ) Class.forName ("builder.link.ClassForNameClassLoaderTest");
        //不执行静态代码块,静态变量不会赋值
        //  Class<?> aClass = ClassLoader.getSystemClassLoader ().loadClass ("builder.link.ClassForNameClassLoaderTest");
        //执行代码块,如果是classloader执行静态代码块 非静态代码块 静态变量赋值
        aClass.newInstance ();
    }
}

1.clssLoader和classForName都是用来加载类的,但是这两个方法一般却又在不同的场景使用。
   如classLoader一般是spring容器用来加载bean的时候使用的,而classForName一般我们都是在使用数据库驱动的时候会使用该方法。
2.了解了两个加载类的不同场景之外后,先看一下类加载的过程。


image.png

2.1 .class文件首先被加载到jvm中
2.2然后经过链接,在链接中有3个步骤。
 首先验证:验证是为了保证我们的.class文件的合法性。会分别尽心文件格式验证,元数据验证,字节码验证,符号引用验证
 然后准备:初始化静态成员变量,并赋值
 最后解析:将符号引用转换为直接引用
2.3初始化,执行静态代码快。类装载过程到此结束

两个方法的底层实现

Class.forName方法
  public static Class<?> forName(String className) 
                throws ClassNotFoundException {
        return forName0(className, true, ClassLoader.getCallerClassLoader());
    }

接着看forName0这个方法

/** Called after security checks have been made. */
    private static native Class forName0(String name, boolean initialize,ClassLoader loader)
    throws ClassNotFoundException;

这里第二个参数initaline表示是否对加载的类进行初始化。
而我们的classforname传入的是true。所以classforname会对类进行初始化操作.

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

继续进入loadClass中,执行loadClass的是传入的false,不初始化类,

 *
     * @param  name
     *         The <a href="#name">binary name</a> of the class
     *
     * @param  resolve
     *         If <tt>true</tt> then resolve the class      true初始化类
     *
     * @return  The resulting <tt>Class</tt> object
     *
     * @throws  ClassNotFoundException
     *          If the class could not be found
     */
    protected synchronized Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
    {
    // First, check if the class has already been loaded
    Class c = findLoadedClass(name);
        //这段就是双亲委派的代码
    if (c == null) {
        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.
            c = findClass(name);
        }
    }
    if (resolve) {
        resolveClass(c);
    }
    return c;
    }

总结两者的区别

Class.forName得到的class是已经初始化完成的
Classloder.loaderClass得到的class是还没有链接的,只是把class加载到jvm中

new和newInstance区别

1.new
①new是一个关键字
②强类型,相对高效,能调用任何public构造。
2.newInstance
①newInstance是一个方法,使用Class.forName或者Classloder.loaderClass获得class,才能调用newInstance方法 (Classloder.loaderClass获取的类,只是jvm加载了该class,并没有后续的链接等一系列的操作,当执行newInstance方法,会从链接开始加载class),调用newInstance返回object和new返回的是一样的.
②弱类型,低效率,只能调用无参构造。

相关文章

网友评论

      本文标题:Class.forName和Classloder.loaderC

      本文链接:https://www.haomeiwen.com/subject/mjeuultx.html