Class.forName和ClassUtils.forName

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

返回一个给定类或者接口的一个 Class 对象,如果没有给定 classloader, 那么会使用根类加载器。如果 initalize 这个参数传了 true,那么给定的类如果之前没有被初始化过,那么会被初始化。可以看到默认是使用的true。注意返回的Class对象是?类型。

我们都知道所有的类都是在对其第一次使用时,动态加载到 JVM。当程序创建第一个对类的静态成员的引用时,就会加载这个类。这也证明了构造器也是类的静态方法,即使在构造器之前并没有 static 关键字。因此,使用 new 操作符创建类的对象也会被当作对类的静态成员的引用。因此 Java 程序在他开始运行之前并非被完全加载,其各个部分是在需要时才加载的。
类加载器首先检查这个类的 Class 对象是否已经加载。如果尚未加载,默认的类加载器就会根据类名称查找 .class 文件。并初始化Class 对象。在加载过程中,该类的 static 子句将会被执行。
可以看到默认使用的是true,但其实他还有一个重载方法,在 ClassUtils 中有使用

Class<?> ClassUtils.forName(“name”, classloader)

这个工具方法和Class.forName方法作用类似,但是他可以初始化数组和带 ;的Class对象

public static Class<?> forName(String name, @Nullable ClassLoader classLoader) throws ClassNotFoundException, LinkageError {

    Assert.notNull(name, "Name must not be null");

    Class<?> clazz = resolvePrimitiveClassName(name);
    if (clazz == null) {
        clazz = commonClassCache.get(name);
    }
    if (clazz != null) {
        return clazz;
    }

    // "java.lang.String[]" style arrays
    if (name.endsWith(ARRAY_SUFFIX)) {
        String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());
        Class<?> elementClass = forName(elementClassName, classLoader);
        return Array.newInstance(elementClass, 0).getClass();
    }

    // "[Ljava.lang.String;" style arrays
    if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(";")) {
        String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1);
        Class<?> elementClass = forName(elementName, classLoader);
        return Array.newInstance(elementClass, 0).getClass();
    }

    // "[[I" or "[[Ljava.lang.String;" style arrays
    if (name.startsWith(INTERNAL_ARRAY_PREFIX)) {
        String elementName = name.substring(INTERNAL_ARRAY_PREFIX.length());
        Class<?> elementClass = forName(elementName, classLoader);
        return Array.newInstance(elementClass, 0).getClass();
    }

    ClassLoader clToUse = classLoader;
    if (clToUse == null) {
        // 获取启动类加载器
        clToUse = getDefaultClassLoader();
    }
    try {
        return Class.forName(name, false, clToUse);
    }
    catch (ClassNotFoundException ex) {
        int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);
        if (lastDotIndex != -1) {
            String innerClassName =
                name.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR + name.substring(lastDotIndex + 1);
            try {
                // 这里使用重载方法,使用上面的启动类加载器,加载到jvm里
                return Class.forName(innerClassName, false, clToUse);
            }
            catch (ClassNotFoundException ex2) {
            }
        }
        throw ex;
    }
}

本文参考:https://www.runoob.com/w3cnote/java-class-forname.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值