前两天头条有朋友留言说使用class.forName找不到类,可以使用classloader加载。趁此机会总结一下,正好看到面试中还经常问到。

一、类加载机制

上面两种加载类的方式说到底还是为了加载一个java类,因此需要先对类加载的过程进行一个简单的了解。我们写好的程序,然后run运行,过程可以直接看下面这张图:

往细了看大致分为5个阶段:

(1)加载:java类运行时候会生成一个class字节码文件,加载的过程就是去我们的操作系统寻找这个class文件。

(2)链接:这个过程就是把class文件加载到java虚拟机。

(3)初始化:在虚拟机中根据class文件进行初始化。

(4)使用:这个过程大家都明白。

(5)卸载:使用完了,java虚拟机进行清理。

对于class.forName和classloader来说针对的就是第一个过程,也就是加载过程。不过这俩虽然有一定的相似性,但是区别还是挺大的。

二、使用举例

我们使用代码,先看看如何使用。注意包的范围,避免加载不了。

第一步:定义User类

public class User {    private static int a = 10;    {        System.out.println("普通代码块");    }    static{        System.out.println("静态变量a:"+a);        System.out.println("静态代码块");    }}

第二步:测试

public class FDDTest {    public static void main(String[] args) {        //注意,我在com.fdd.reflect包下建的类        String user = "com.fdd.reflect.User";        test(user);    }       public static void test(String user) {        try {            ClassLoader loader = ClassLoader.getSystemClassLoader();            System.out.println("classloader testing...");            Class> loaderUser = loader.loadClass(user);            System.out.println("user " + loaderUser.getName());            System.out.println("---------------------------------------");             Class forNameUser = Class.forName(user);            System.out.println("Class.forName testing...");            System.out.println("user " + forNameUser.getName());        } catch (ClassNotFoundException e){            e.printStackTrace();        }    }}

我们在上面的test方法中,使用了两个加载方法。现在我们测试一下:

classloader testing...user com.fdd.reflect.User---------------------------------------静态变量a:10静态代码块Class.forName testing...user com.fdd.reflect.User

是不感觉有点区别。现在是先给出一个大体的使用,下面我们分析一下他们的区别。

三、区别

1、class.forName

class.forName()前者除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。注意这里的静态块指的是在类初始化时的一些数据。但是classloader却没有,想要弄清楚这个原因,还是直接到源码中看看。

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

在这个源码中我们会发现,其实底层真正实现的是forName0方法,那这几个参数又是什么意思呢?

(1)className:表示我们要加载的类名

(2)true:指Class被加载后是不是必须被初始化。不初始化就是不执行static的代码即静态代码,在这里默认为true,也就是默认实现类的初始化。

(3)ClassLoader.getClassLoader(caller):表示类加载器,到这你会发现forNanme其实也是使用的ClassLoader类加载器加载的。

(4)caller:指定类加载器。

所以,在这里你可以指定是否在class加载后被初始化。而且底层还是使用的classloader加载的。

2、classloader

在上面的案例中我们发现,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)) {        // 首先检查这个类是否已经被加载        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) {}            if (c == null) {                long t1 = System.nanoTime();                c = findClass(name);                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);                 sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);                sun.misc.PerfCounter.getFindClasses().increment();            }        }        //如果已经加载了,那就重新加载       if (resolve) {            resolveClass(c);        }        return c;    }}

这个才是真正实现的方法,在这里的步骤其实很简单,大致流程是先判断class是否已经被加载,如果被加载了那就重新加载,如果没有加载那就使用双亲委派原则加载。加载的时候并没有指定是否要进行初始化。

所以现在他们的区别基本上很少,总结一下:

(1)class.forName()除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。当然还可以指定是否执行静态块。

(2)classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。

有一个小问题需要注意:我在网上看了几篇文章,亲测有错误,那就是class.forName其实是不会执行静态方法的,但是会初始化静态变量。错误的例子是使用了静态方法为静态变量赋值了。

ok,一个小知识点。如有问题,还请批评指正。

class mywnd : pubic qwidget是什么意思_学了这么久java反射,你知道class.forName和classloader的区别吗?...相关推荐

  1. java string 常量池_用了这么久Java String,你真的懂字符串常量池吗?

    字符串问题可谓是 Java 中经久不衰的问题,尤其是字符串常量池经常作为面试题出现.可即便是看似简单而又经常被提起的问题,还是有好多同学一知半解,看上去懂了,仔细分析起来却又发现不太明白. 本文以 J ...

  2. java反射获取方法内部_公共技术点之 Java 反射 Reflection

    本文为 Android 开源项目源码解析 公共技术点中的 Java 反射 部分 分析者:Mr.Simple,校对者:Trinea,校对状态:未完成 1. 了解 Java 中的反射 1.1 什么是 Ja ...

  3. java resume过时方法_学点开发|关于Java多线程用法解析

    在进行学习之前,我们先来了解下,什么是Java多线程: 多线程是实现并发机制的一种有效手段.进程和线程一样,都是实现并发的一个基本单位.为了让大家更清晰读懂关于Java多线程用法,由以下几点入手学,帮 ...

  4. java反射构造函数_【译】3. Java反射——构造函数

    ==================================================================================================== ...

  5. 方向盘左右能摇动_学车这么久了,你还不会打方向盘呢?

    刚刚学车的朋友肯定有过这样的问题: 教练说:往左打两圈,往右打一圈,往左打半圈--你乖乖听话照做,然后教练说:回正吧. 是不是一下就蒙住了??我刚才打几圈来着??往哪边转是回正啊?? 我们知道方向盘上 ...

  6. java 反射机制 视频_【视频笔记】Java反射机制笔记

    Java 语言的反射机制 在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法.对于任意一个对象,可以调用它的任意一个方法. 这种动态获取类的信息以及动态调用对象的方法的功能来自于J ...

  7. java 数组 反射_【译】10. Java反射——数组

    ===================================================================================== 用Java反射来处理数组有时 ...

  8. dwr java有返回值但是js获取不到返回值_一探究竟:Java反射效率低的原因到底在哪?...

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低的原因 文章概览 我们在 Java 开发中,难免会接触到反射,而在一些框架中,反射的运 ...

  9. python method与function方法_学编程这么久,还傻傻分不清什么是方法(method),什么是函数(function)?...

    在编程语言中有两个很基础的概念,即方法(method)和函数(function).如果达到了编程初级/入门级水平,那么你肯定在心中已有了初步的答案. 也许在你心中已有答案了 除去入参.返回值.匿名函数 ...

最新文章

  1. 嵌入式开发在过去20年中是如何演变的
  2. Py之wxPython:利用wxPython设计CMD软件窗口进行交互可视化
  3. 如何搭建MGRE——实验
  4. Oracle Rman 命令详解(List report backup configure)
  5. 优化案例(part8)--Robust Recovery of Subspace Structures by Low-Rank Representation
  6. Tomcat简单介绍
  7. @Configuration和@Bean注解详解
  8. php trait编译实现,为什么PHP Trait不能实现接口?
  9. 2.分布式服务架构:原理、设计与实战 --- 彻底解决分布式系统一致性的问题
  10. python读取fiddler_Python3.x+Fiddler抓取APP数据
  11. Labview完全卸载工具msiblast NI
  12. NVIDIA史上最大显卡质量事故,我正在用Vostro 1400
  13. 【软件工程】层次图、HIPO图——期末快速复习用
  14. 今天不开心 和话痨机器人聊一会
  15. 8.如何在idea打开一个已有项目
  16. 《写给大家看的设计书》读后
  17. 计算机学院文化长廊,计算机学院2019年寝室文化节动员大会顺利召开
  18. 二维码的生成和解析原理
  19. 能够有效提升开发效率的 20 余款 VSCode 插件(多图带效果展示)
  20. 【更新】京东、美团、饿了么获取cookies

热门文章

  1. C#模拟POST提交表单(一)--WebClient
  2. SecureCRT 连接虚拟机Linux
  3. 项目经理人必须要遵循的14个成功原则
  4. php利用openssl实现RSA非对称加密签名
  5. 微博遭鹿晗恋情暴击瘫痪,如何快速提高系统性能?
  6. Nginx+Lua(OpenResty) HelloWorld
  7. ELK错误1_Kafka-Logstash-Elasticsearch过程,Elasticsearch报grokparsefailure错误
  8. Git的SourceTree添加授权添加用户名与密码
  9. MySQL安装sql追踪器phpgjx
  10. Linux之Centos允许root连接ftp