class mywnd : pubic qwidget是什么意思_学了这么久java反射,你知道class.forName和classloader的区别吗?...
前两天头条有朋友留言说使用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的区别吗?...相关推荐
- java string 常量池_用了这么久Java String,你真的懂字符串常量池吗?
字符串问题可谓是 Java 中经久不衰的问题,尤其是字符串常量池经常作为面试题出现.可即便是看似简单而又经常被提起的问题,还是有好多同学一知半解,看上去懂了,仔细分析起来却又发现不太明白. 本文以 J ...
- java反射获取方法内部_公共技术点之 Java 反射 Reflection
本文为 Android 开源项目源码解析 公共技术点中的 Java 反射 部分 分析者:Mr.Simple,校对者:Trinea,校对状态:未完成 1. 了解 Java 中的反射 1.1 什么是 Ja ...
- java resume过时方法_学点开发|关于Java多线程用法解析
在进行学习之前,我们先来了解下,什么是Java多线程: 多线程是实现并发机制的一种有效手段.进程和线程一样,都是实现并发的一个基本单位.为了让大家更清晰读懂关于Java多线程用法,由以下几点入手学,帮 ...
- java反射构造函数_【译】3. Java反射——构造函数
==================================================================================================== ...
- 方向盘左右能摇动_学车这么久了,你还不会打方向盘呢?
刚刚学车的朋友肯定有过这样的问题: 教练说:往左打两圈,往右打一圈,往左打半圈--你乖乖听话照做,然后教练说:回正吧. 是不是一下就蒙住了??我刚才打几圈来着??往哪边转是回正啊?? 我们知道方向盘上 ...
- java 反射机制 视频_【视频笔记】Java反射机制笔记
Java 语言的反射机制 在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法.对于任意一个对象,可以调用它的任意一个方法. 这种动态获取类的信息以及动态调用对象的方法的功能来自于J ...
- java 数组 反射_【译】10. Java反射——数组
===================================================================================== 用Java反射来处理数组有时 ...
- dwr java有返回值但是js获取不到返回值_一探究竟:Java反射效率低的原因到底在哪?...
预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低的原因 文章概览 我们在 Java 开发中,难免会接触到反射,而在一些框架中,反射的运 ...
- python method与function方法_学编程这么久,还傻傻分不清什么是方法(method),什么是函数(function)?...
在编程语言中有两个很基础的概念,即方法(method)和函数(function).如果达到了编程初级/入门级水平,那么你肯定在心中已有了初步的答案. 也许在你心中已有答案了 除去入参.返回值.匿名函数 ...
最新文章
- 嵌入式开发在过去20年中是如何演变的
- Py之wxPython:利用wxPython设计CMD软件窗口进行交互可视化
- 如何搭建MGRE——实验
- Oracle Rman 命令详解(List report backup configure)
- 优化案例(part8)--Robust Recovery of Subspace Structures by Low-Rank Representation
- Tomcat简单介绍
- @Configuration和@Bean注解详解
- php trait编译实现,为什么PHP Trait不能实现接口?
- 2.分布式服务架构:原理、设计与实战 --- 彻底解决分布式系统一致性的问题
- python读取fiddler_Python3.x+Fiddler抓取APP数据
- Labview完全卸载工具msiblast NI
- NVIDIA史上最大显卡质量事故,我正在用Vostro 1400
- 【软件工程】层次图、HIPO图——期末快速复习用
- 今天不开心 和话痨机器人聊一会
- 8.如何在idea打开一个已有项目
- 《写给大家看的设计书》读后
- 计算机学院文化长廊,计算机学院2019年寝室文化节动员大会顺利召开
- 二维码的生成和解析原理
- 能够有效提升开发效率的 20 余款 VSCode 插件(多图带效果展示)
- 【更新】京东、美团、饿了么获取cookies
热门文章
- C#模拟POST提交表单(一)--WebClient
- SecureCRT 连接虚拟机Linux
- 项目经理人必须要遵循的14个成功原则
- php利用openssl实现RSA非对称加密签名
- 微博遭鹿晗恋情暴击瘫痪,如何快速提高系统性能?
- Nginx+Lua(OpenResty) HelloWorld
- ELK错误1_Kafka-Logstash-Elasticsearch过程,Elasticsearch报grokparsefailure错误
- Git的SourceTree添加授权添加用户名与密码
- MySQL安装sql追踪器phpgjx
- Linux之Centos允许root连接ftp