java的反射通过类名java 类加载与反射类和ClassLoader通过类名java 类加载与反射类有什么区别

3497人阅读
Java学习笔记(20)
& & & &&原创作品。转载请注明出处& & & & 摘要:本文主要讲了Java类加载的机制,这是学习反射的入门基础。一、类加载JVM和类& & & 当我们调用Java命令运行某个Java程序时,该命令将会启动一条Java虚拟机进程,不管该Java程序有多么复杂,该程序启动了多少个线程,它们都处于该Java虚拟机进程里。正如前面介绍的,同一个JVM的所有线程、所有变量都处于同一个进程里,它们都使用该JVM进程的内存区。当系统出现以下几种情况时,JVM进程将被终止:1、程序运行到最后正常结束。2、程序运行到使用System.exit()或Runtime.getRuntime().exit()代码结束程序。3、程序执行过程中遇到未捕获的异常或错误而结束。3、程序所在平台强制结束了JVM进程。从上面的介绍可以看出,当Java程序运行结束时,JVM进程结束,该进程在内存中状态将会丢失。类的生命周期类的加载/类初始化& & &当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过加载、连接、初始化三个步骤来对该类进行初始化,如果没有意外,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载或类初始化。加载:查找并加载类的二进制数据& && 1、通过一个类的全限定名来获取定义此类的二进制字节流。2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。3、在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口。注意:将编译后的java类文件(也就是.class文件)中的二进制数据读入内存,并将其放在运行时数据区的方法区内,然后再堆区创建一个Java.lang.Class对象,用来封装类在方法区的数据结构。即加载后最终得到的是Class对象,并且更加值得注意的是:该Java.lang.Class对象是单实例的,无论这个类创建了多少个对象,他的Class对象时唯一的!连接:& & & & 1、验证:确保被加载的类的正确性& & & & 2、准备:为类的静态变量分配内存,并将其初始化为默认值& & & & 3、解析:把类中的符号引用转换为直接引用。初始化:为类的静态变量赋予正确的初始值。注意:连接和初始化阶段,其实静态变量经过了两次赋值:第一次是静态变量类型的默认值;第二次是我们真正赋给静态变量的值。我简单画了个图,其过程如下:&类加载指的是将类的class文件读入内存,并为之创建一个java.lang.Class对象,也就是说当程序中使用任何类时,系统都会为之建立一个java.lang.Class对象。事实上,每个类是一批具有相同特征的对象的抽象(或者说概念),而系统中所有的类,它们实际上也是对象,它们都是java.lang.Class的实例。& & 加载由类加载器完成,类加载器通常由JVM提供,这些类加载器也是我们前面所有程序运行的基础,JVM提供的这些类加载器通常被称为系统类加载器。除此之外,开发者可以通过继承ClassLoader基类来创建自己的类加载器。通过使用不同的类加载器,可以从不同来源加载类的二进制数据,通常有如下几种来源:1、从本地文件系统来加载class文件,这是绝大部分示例程序的类加载方式。2、从JAR包中加载class文件,这种方式也是很常见的,前面介绍JDBC编程时用到的数据库驱动类就是放在JAR文件中,JVM可以从JAR文件中直接加载该class文件。3、通过网络加载class文件。4、把一个Java源文件动态编译、并执行加载。类加载器通常无须等到“首次使用”该类时才加载该类,Java虚拟机规范允许系统预先加载某些类。&Java程序对类的使用方式主动使用1、创建类的实例2、方法某个类或接口的静态变量,或者对该静态变量赋值3、调用类的静态方法4、反射(如 Class.forName(“com.itzhai.Test”))5、初始化一个类的子类6、Java虚拟机启动时被标明为启动类的类(Main Class)被动使用除了以上6中方式,其他对类的使用都是被动使用,都不会导致类的初始化。类的初始化时机正是java程序对类的首次主动使用,所有的Java虚拟机实现必须在每个类或接口被Java程序“首次主动使用”时才初始化它们。&对象初始化在类被装载、连接和初始化,这个类就随时都可能使用了。对象实例化和初始化是就是对象生命的起始阶段的活动,在这里我们主要讨论对象的初始化工作的相关特点。Java 编译器在编译每个类时都会为该类至少生成一个实例初始化方法--即&&init&()& 方法。此方法与源代码中的每个构造方法相对应,如果类没有明确地声明任何构造方法,编译器则为该类生成一个默认的无参构造方法,这个默认的构造器仅仅调用父类的无参构造器,与此同时也会生成一个与默认构造方法对应的 &&init&()& 方法.通常来说,&init&() 方法内包括的代码内容大概为:调用另一个 &init&() 方法;对实例变量初始化;与其对应的构造方法内的代码。如果构造方法是明确地从调用同一个类中的另一个构造方法开始,那它对应的 &init&() 方法体内包括的内容为:一个对本类的 &init&() 方法的调用;对应用构造方法内的所有字节码。如果构造方法不是通过调用自身类的其它构造方法开始,并且该对象不是 Object 对象,那 &init&() 法内则包括的内容为:一个对父类 &init&() 方法的调用;对实例变量初始化方法的字节码;最后是对应构造子的方法体字节码。如果这个类是 Object,那么它的 &init&() 方法则不包括对父类 &init&() 方法的调用。二、Class.forName、实例对象.class(属性)、实例对象getClass()的区别1、相同点:通过这几种方式,得到的都是Java.lang.Class对象(这个是上面讲到的类在加载时获得的最终产物)例如:package com.
* 功能概要:
* @author linbingwen
public class people {
* @author linbingwen
* @param args
public static void main(String[] args) throws Exception {
System.out.println(&..............使用不同的方式加载类...................&);
System.out.println(people.class);//通过类.class获得Class对象
people a = new people();
System.out.println(a.getClass());//通过 实例名.getClass()获得Class对象
System.out.println(Class.forName(&com.lin.people&));//通过Class.forName(全路径)获得Class对象
System.out.println(&..............使用不同的方式创建对象...................&);
System.out.println(a);//使用不同的方式创建对象
System.out.println(people.class.newInstance());
System.out.println(a.getClass().newInstance());
System.out.println(Class.forName(&com.lin.people&).newInstance());
结果:从上面可以看到不同的方式加载类。其实这一过程只发生一次!2、区别:下面用一个实例来说说它们的区别如下新建一个类package com.
* 功能概要:
* @author linbingwen
public class Cat {
System.out.println(&生成了一只猫&);
然后开始使用:package com.
* 功能概要:
* @author linbingwen
public class CatTest {
* @author linbingwen
* @param args
public static void main(String[] args) throws Exception{
System.out.println(&---------------Cat.class开始------------------&);
System.out.println(Cat.class);//通过类.class获得Class对象
System.out.println(&---------------Cat.class结束------------------&);
System.out.println(&---------------Class.forName开始------------------&);
System.out.println(Class.forName(&com.lin.Cat&));//通过Class.forName(全路径)获得Class对象
System.out.println(&---------------Class.forName结束------------------&);
System.out.println(&---------------cat.getClass()开始------------------&);
Cat cat = new Cat();
System.out.println(cat.getClass());//通过Class.forName(全路径)获得Class对象
System.out.println(&---------------cat.getClass()结束------------------&);
输出结果:如果,将Class.forName()去掉:如下:package com.
* 功能概要:
* @author linbingwen
public class CatTest {
* @author linbingwen
* @param args
public static void main(String[] args) throws Exception{
System.out.println(&---------------Cat.class开始------------------&);
System.out.println(Cat.class);//通过类.class获得Class对象
System.out.println(&---------------Cat.class结束------------------&);
System.out.println(&---------------Class.forName开始------------------&);
System.out.println(Class.forName(&com.lin.Cat&));//通过Class.forName(全路径)获得Class对象
System.out.println(&---------------Class.forName结束------------------&);
System.out.println(&---------------cat.getClass()开始------------------&);
Cat cat = new Cat();
System.out.println(cat.getClass());//通过Class.forName(全路径)获得Class对象
System.out.println(&---------------cat.getClass()结束------------------&);
}结果又变成:所以,可以得出以下结论:1)Class cl=Cat.&JVM将使用类Cat的类装载器,将类A装入内存(前提是:类A还没有装入内存),不对类A做类的初始化工作.返回类A的Class的对象2)Class cl=对象引用o.getClass();返回引用o运行时真正所指的对象(因为:儿子对象的引用可能会赋给父对象的引用变量中)所属的类的Class的对象 ,如果还没装载过,会进行装载。3)Class.forName(&类名&);&装入类A,并做类的初始化(前提是:类A还没有装入内存)三、new和newInstance()从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用Class对象的newInstance()方法的时候,就必须保证:1、这个类已经加载;2、这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载 java API的那个加载器。&现在可以看出,Class对象的newInstance()(这种用法和Java中的工厂模式有着异曲同工之妙)实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。&Class.forName().newInstance()和通过new得到对象的区别1、使用newInstance可以解耦。使用newInstance的前提是,类已加载并且这个类已连接,这是正是class的静态方法forName()完成的工作。newInstance实际上是把new 这个方式分解为两步,即,首先调用class的加载方法加载某个类,然后实例化。2、newInstance: 弱类型。低效率。只能调用无参构造。 new: 强类型。相对高效。能调用任何public构造。&3、newInstance()是实现IOC、反射、面对接口编程和依赖倒置等技术方法的必然选择,new只能实现具体类的实例化,不适合于接口编程。&4、 newInstance() 一般用于动态加载类。5、Class.forName(“”).newInstance()返回的是object 。6、newInstance( )是一个方法,而new是一个关键字;注:一般在通用框架里面用的就是class.forName来加载类,然后再通过反射来调用其中的方法,譬如Tomcat源码里面,这样就避免了new关键字的耦合度,还有让不同的类加载器来加载不同的类,方便提高类之间的安全性和隔离性.
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1740302次
积分:18154
积分:18154
排名:第548名
原创:275篇
评论:1344条
阅读:51149
阅读:80383
文章:13篇
阅读:91771
文章:18篇
阅读:159426
文章:23篇
阅读:227034
(10)(10)(10)(1)(10)(4)(10)(10)(1)(6)(4)(6)(3)(12)(10)(11)(12)(14)(21)(28)(13)(16)(15)(4)(2)(13)(16)(2)(1)12:35 提问
在java程序中如何加载自己写的类?
package org.zeng.
public class TestReflection {
public static void main(String[] args) {
//new S();
Class.forName("S");
ClassLoader.getSystemClassLoader().loadClass("S"); // 用AppClassLoader加载
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.out.println("S is loaded!");
public S() {
System.out.println("S is instance!");
报java.lang.ClassNotFoundException: S 这样的错误,有大神知道吗? 另外这2个加载方法有区别吗????
按赞数排序
完整类名,要加包的,因为,class.forname(),要求类唯一,不写包名类名是不唯一的
Class.forName(String className)使用装载当前类的类装载器来装载指定类。因为class.forName(String className)方法内部调用了Class.forName(className,true, this.getClass().getClassLoader())方法,如你所见,第三个参数就是指定类装载器,显而易见,它指定的是装载当前类的类装载器的实例,也就是this.getClass().getClassLoader();
classLoader.loadClass(StringclassName , boolean resolve);需要手动指定类装载器的实例。
所以这两种类装载方式的区别之一是一个默认使用装载当前类实例的类装载器来装载指定类,而另一个则需要手动指定一个类装载器的实例。
把S那个类放在外面去,或者放在另外一个包下面试试。加载的时候把包名也写上、。
----------------------biu~biu~biu~~~在下问答机器人小D,这是我依靠自己的聪明才智给出的答案,如果不正确,你来咬我啊!
如果程序需要Class被实例化,就必须用Class.forName(name)了。S没有实例化
其他相关推荐java类加载器和类反射使用示例
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了java类加载器和类反射使用示例,需要的朋友可以参考下
一、一个命令对应一个进程。
当我们启动一个Java程序,即启动一个main方法时,都将启动一个Java虚拟机进程,不管这个进程有多么复杂。而不同的JVM进程之间是不会相互影响的。这也就是为什么说,Java程序只有一个入口——main方法,让虚拟机调用。而两个mian方法,对应的是2个JVM进程,启动的是两个不同的类加载器,操作的实际上是不同的类。故而不会互相影响。
二、类加载。
当我们使用一个类,如果这个类还未加载到内存中,系统会通过加载、连接、初始化对类进行初始化。
1、类加载:指的是将类的class文件读入JVM,并为之创建一个Class对象。
2、类连接:指的是把类的二进制数据合并到JRE中,这又分为3个阶段:
a)、校验:检查载入Class文件数据的正确性。
b)、准备:给类的静态变量分配存储空间,并进行默认初始化。
c)、解析:将类的二进制数据中的符号引用替换成直接引用。
3、初始化:对类的静态变量、静态初始化块进行初始化。
(注意:一个final类型的静态属性,如果在编译时已经得到了属性值,那么调用该属性时,不会导致该类初始化,因为这个相当于使用常量;
使用ClassLoader()方法,只是加载该类,并未初始化。)
三、类加载器。
类加载器就是负责将.class文件加载到内存中,并为之生成对应的java.lang.Class对象,它负责加载所有的类,而一旦一个类被加载入JVM中,就不会被再次载入了。
在Java中,一个类用其全限定类名(即包名+类名)作为标识。
而在JVM中,一个类用其全限定类名和其类加载器作为标识。
JVM运行时会产生3个ClassLoader,分别为:BootstrapClassLoader(根类加载器)、ExtClassLoader(扩展类加载器)和AppClassLoader(系统类加载器)。UML结构如下:
其中,BootstrapClassLoader负责加载JRE的核心类库,它不是ClassLoader的子类,使用C++编写,因此我们在Java中看不到它,通过其子类的getParent()方法获取时,将返回null。BootstrapClassLoader负责装载JRE目标下的rt.jar、charsets.jar等Java核心类库。
如图可知,ExtClassLoader和AppClassLoader为ClassLoader的子类。在API中看不到它们,他们位于rt.jar文件中。全限定类名分别为:
sun.misc.Launcher$ExtClassLoader 和 sun.misc.Launcher$AppClassLoader.
其中,ExtClassLoader负责装载JRE扩展目录ext中JAR包,而AppClassLoader负责装载Classpath路径下的类包。
测试如下:
代码如下:package com.stopTalking.public class TestClassLoader {public static void main(String[] args) { //获取当前线程的类装载器& ClassLoader loader = Thread.currentThread().getContextClassLoader();& //获取System类的类装载器& ClassLoader loader1 = System.class.getClassLoader();& //获取本类TestClassLoader的类装载器loader2& ClassLoader loader2 = TestClassLoader.class.getClassLoader();& //获取loader2的父类& ClassLoader loader3 = loader2.getParent();& //获取loader2的父类的父类& ClassLoader loader4 = loader3.getParent();& System.out.println(loader);& System.out.println(loader1);& System.out.println(loader2);& System.out.println(loader3);& System.out.println(loader4);& }& }
控制台输出:
代码如下://当前线程类获取的类加载器是AppClassLoadersun.misc.Launcher$AppClassLoader@6b97fd//System类为根装载器加载,java中访问不到,所以为nullnull//本类的类加载器当然也是AppClassLoadersun.misc.Launcher$AppClassLoader@6b97fdsun.misc.Launcher$ExtClassLoader@1c78e57null
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具java中反射机制及其类加载的几种方式的异同 - CSDN博客
java中反射机制及其类加载的几种方式的异同
一、Java中反射机制总结:
反射的定义:通过反射,把Java类中的各个组成部分映射到相应的Java类
反射的优点:
1.&减少对象的依赖,调用方法更灵活,改变属性的值。
2.&通过class对象得到该类的对象,从而获取到方法等。
3.&提高程序的扩展性
首先通过程序来演示一下反射原理:
有一个实体类Student.java
package com.huaxin.
* @author 赵芳
* 日 下午5:23:30
public class Student {
public String name = &abcd&;
* @param string
public Student(String name) {
System.out.println(&调用有一个参数的构造方法创建对象&);
this.name =
public Student() {
System.out.println(&调用无参数构造方法创建对象&);
public String toString() {
return &Student [name=& + name + &]&;
public void study(){
System.out.println(name+&学习&);
一个测试类Test.java
package com.huaxin.
import java.lang.reflect.C
import java.lang.reflect.F
import java.lang.reflect.M
* java中反射机制的测试
* @author 赵芳
上午9:56:15
public class Test {
public static void main(String[] args) throws Exception{
//通过反射获取构造方法Constructor
Class c = Class.forName(&com.huaxin.reflect.Student&);
Constructor cons = c.getDeclaredConstructor(String.class);
cons.setAccessible(true);//访问权限
Student stu = (Student) cons.newInstance(&bbb&);
System.out.println(stu);
//使用new关键字创建对象
Student stu1 = new Student(&aaa&);
System.out.println(stu1);
// 创建此 Class 对象所表示的类的一个新实例,只能是无参
Student stu2 = (Student) c.newInstance();
System.out.println(stu2);
//通过反射获取Field,并且该属性在此类中是public的,否则会抛出NoSuchFieldException
Field field_name = c.getField(&name&);
System.out.println(field_name.get(stu));
//通过反射来调用方法Method
Method method = c.getMethod(&study&, null);
method.invoke(stu2, null);
输出结果:
调用有一个参数的构造方法创建对象
Student [name=bbb]
调用有一个参数的构造方法创建对象
Student [name=aaa]
调用无参数构造方法创建对象
Student [name=abcd]
每个Java程序执行前都必须经过编译、加载、连接和初始化这几个阶段,后三个阶段如下图:
(1)加载是指将编译后的java类文件(.class文件)中的二进制数据读入内存,并将其放在运行时数据区的方法区内,然后再堆区创建一个java.lang.Class对象,用来封装类在方法区的数据结构。即加载后最终得到的是Class对象,并且更加值得注意的是:该Java.lang.Class对象是单实例的,无论这个类创建了对少个对象,它的Class对象是唯一的!而加载并获取该Class对象可以通过三种途径:Class.forName(类的全名称)、实例对象.class(属性)、实例对象getClass()。
(2)在连接和初始化阶段,其实静态变量经过了两次赋值:第一次是静态变量类型的默认值;第二次是我们真正赋给静态变量的值。
(3)Java对类的使用分为两种方式:主动使用和被动使用。其中主动使用的方式有以下6种,
①创建类的实例
②访问某个类或接口的静态变量,或者对该静态变量赋值
③调用类的静态方法
④反射(如Class.forName(“java.lang.String”))
⑤初始化一个类的子类
⑥Java虚拟机启动时被标明为启动类的类
而类的初始化时机正是java程序对类的首次主动使用,除了以上6种方式,其他对类的使用都是被动使用,都不会导致类的初始化。并且应注意以下几个方面:
①调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化。
②当java虚拟机初始化一个类时,要求它的所有父类都已经被初始化,但是这条规则并不适用于接口。
l& 在初始化一个类时,并不会先初始化它所实现的接口。
l& 在初始化一个接口时,并不会先初始化它的父接口。
因此,一个父接口并不会因为它的子接口或者实现类的初始化而初始化。只有当程序首次使用特定接口的静态变量时,才会导致该接口的初始化。
在这里可以看出,接口的两重性:可以把接口当做类(因为在接口中有静态变量时,可以被初始化);接口就是接口,和类无关(接口中没有构造方法,所以不能被初始化)。
二、Class.forName、实例对象.class(属性)、实例对象getClass()的异同:
通过这几种方式,得到的都是java.lang.Class对象
①&Classc1 = String.JVM将使用String类的类装载器,将String类装入内存(前提是String类还没有装入内存),不对String类做类的初始化工作,返回String类的Class对象。
②&Class.forName(“类名”);装入类**,并做类的初始化
③&Class= 对象引用o.getClass();返回引用对象o运行时真正所指的对象(因为儿子对象的引用可能会赋给父对象的引用变量中)所属的类的Class对象
从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用Class对象的newInstance()方法的时候,就必须保证:1.这个类已经加载;2.这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载java API的那个加载器。
&&& 现在可以看出,Class对象的newInstance()实际上是把new这个方法分解为两步,即首先调用Class加载方法加载某个类,然后实例化。这样分布的好处:我们可以在调用Class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。
&&& 最后,用最简单的描述来区分new关键字和newInstance()方法的区别:
newInstance:弱类型,低效率,只能调用无参构造;
new:强类型,相对高效,能调用任何Public构造。
本文已收录于以下专栏:
相关文章推荐
首先先来看一下JAVA反射的概念:
JAVA反射(Reflection):在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获...
同一个JVM的有线程、所有变量都处于同一个进程里,他们都使用JVM进程的内存区。当系统出现以下几种情况时JVM进程将被终止:
1、程序运行到最后正常结束
2、程序运行到使用System.exit()或...
在class文件中的描述信息都需要加载到jvm才能运行和使用。
jvm的类加载机制:jvm把描述类的数据从class文件中加载到内存,并对数据进行校验,转换解析,和初始化,最终形成被jvm...
接下来介绍下JAVA中非常重要的一个类ClassLoader(类装载器)
类装载器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件。主要工作由ClassLoader及其子类负责,Clas...
参考文献:
1. 《深入理解JVM虚拟机》
实现给私有属性赋值Field
field_qt = form.gettSswageTrtmt().getCla...
getFields()与getDeclaredFields()区别:getFields()只能访问类中声明为公有的字段,私有的字段它无法访问,能访问从其它类继承来的公有方法.getDeclaredFi...
现在做项目都会使用框架,现在很常见的框架就是SSH(Struts+SpringMVC+Spring+Hibernate),SSM(Struts/springMVC+Spring+Hibernate),...
上个月,idea的使用量超越eclipse的消息席卷了整个IT界,idea到底好在哪里呢?
最智能的IDEIDEA相对于eclipse来说最大的优点就是它比eclipse聪明。聪明到什么程度呢?我们先...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)博客分类:
&&&& java中class.forName和classLoader都可用来对类进行加载。前者除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。而classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。Class.forName(name, initialize, loader)带参函数也可控制是否加载static块。并且只有调用了newInstance()方法采用调用构造函数,创建类的对象
事例代码如下:
1.使用classLoader加载
&&& System.out.println("before loadClass... ");
&&& Class c =Test.class.getClassLoader().loadClass("com.hundsun.test.ClassInfo");
&&& System.out.println("after loadClass... ");
&&& System.out.println("before newInstance... ");
&&& ClassInfo info1 =(ClassInfo) c.newInstance();
&&& System.out.println("after newInstance... ");
输出结果:
before loadClass...
after loadClass...
before newInstance...
static invoked...
contruct invoked...
after newInstance...
2.使用class.forName进行加载
System.out.println("before class.forName");
Class cc =Class.forName("com.hundsun.test.ClassInfo");
System.out.println("after class.forName");
ClassInfo info2 =(ClassInfo) cc.newInstance();
输出结果:
before class.forName
static invoked...
after class.forName
before newInstance...
contruct invoked...
after newInstance...
下面说一下两者具体的执行过程
LoadClass()方法加载类及初始化过程:
类加载(loadclass())(加载)——》newInstance()(链接+初始化)
newInstance():
(开始连接)静态代码块——》普通变量分配准备(a=0;b=0;c=null)——》(开始初始化)普通变量赋值(a=1;b=2;c=”haha”)——》构造方法——》初始化成功。
Class.forName(Stirng className)一个参数方法加载类及初始化过程:
类加载(Class.forName())(加载)——》静态代码块——》newInstance()(链接+初始化)
newInstance():
(开始连接)普通变量分配准备(a=0;b=0;c=null)——》(开始初始化)普通变量赋值(a=1;b=2;c=”haha”)——》构造方法——》初始化成功。
Class.forName()三个参数的加载类及初始化过程同classLoader一样。
从上边的断点调试可以看出,静态代码块不是在初始化阶段完成的,它陷于类初始化,先于普通变量默认分配(整型分配为0,字符串分配为null),这也就是为什么我们不能在静态代码块中引用普通变量的原因之一,这与上面所谓的“分配”、“初始化”相违背。
所以我觉得JVM的类加载及初始化过程应该是这样的。
1. 类加载:Bootstrap Loader——》Extended Loader——》System Loader
2. 静态代码块初始化
3. 链接:
a) 验证:是否符合java规范
b) 准备:默认初始值
c) 解析:符号引用转为直接引用,解析地址
4. 初始化
a) 赋值:java代码中的初始值
b) 构造:构造函数
浏览: 49467 次
来自: 杭州
确实管用。
这是exjts3去除拖动效果的处理方法,不知道有没有extjs ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 java 通过类名反射 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信