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) 构造:构造函数
分享到:
相关推荐
10. **类加载器的简化方式**:Java还提供了一种更简洁的方式来加载资源,如`InputStream ips = ReflectTest2.class.getResourceAsStream("config.properties");`,这将从当前类的路径下寻找资源文件,不需要以`/`...
8. **Class.forName与ClassLoader**:`Class.forName()`是静态方法,通过类名加载类;ClassLoader是动态加载类的机制,可以自定义加载策略。 9. **动态代理**:Java提供了JDK动态代理和CGLIB两种实现,前者基于接口...
`findClass()`方法用于加载类的字节码数据。 #### 动态代理 **JDK动态代理**: 1. **代理原理**:JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。通过实现`...
类的加载通常发生在以下几种情况:创建新对象、继承、JVM指定启动类、访问静态变量或方法、使用`Class.forName()`以及对`static final`变量的引用。加载过程包括加载、连接(验证、准备、解析)和类的初始化(静态...
Class<?> clazz = Class.forName("Data"); Constructor<?> constructor = clazz.getConstructor(); Data data = (Data) constructor.newInstance(); Method method = clazz.getMethod("getData"); System.out....
- **通过类的加载器获取**:`Class.forName()`, `ClassLoader.loadClass()`. - **通过实例对象获取**:`instance.getClass()`. - **通过类名获取**:`SomeClass.class`. #### 22. 如何唤起类中的一个方法? 可以...
类的加载又分为显式(如`Class.forName`)和隐式(如`new`关键字)。 2. **HashMap的实现机制**: - HashMap基于哈希表实现,它将key-value对看作一个整体,通过数组索引来定位存储位置。 - 允许null值和null键。...
27. **Class.forName(String className)这个方法的作用** - 加载指定名称的类,并返回对应的Class对象。 28. **int和Integer的区别** - `int`是基本数据类型,`Integer`是`int`的包装类。 29. **位运算** - 位...
15.1.2 使用class.forname() 502 15.1.3 从class获得信息 503 15.1.4 从class建立对象 506 15.1.5 操作对象方法与成员 509 15.1.6 动态代理 512 15.2 了解类加载器 515 15.2.1 类加载器层级架构 515 ...
声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其...
【反射】反射中,Class.forName和classloader的区别 42 【JVM】JAVA编译原理和JVM原理 42 【JVM】Java内存模型 44 【JVM】jvm内存模型 45 主内存与工作内存 45 内存间交互操作 46 重排序 48 【JVM】内存泄漏 49 ...
声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,...
在Java应用程序的世界中,启动器(Launcher)起着至关重要的作用,它负责解析命令行参数,设置环境变量,加载类并执行主方法。TNFLauncher是这样一个启动器的实现,其源码提供了深入理解Java应用程序启动流程的机会...
- **定义**: 负责加载应用程序类路径中的类。 **7.25 全盘负责委托机制** - **说明**: 类加载器之间的层次结构及委托关系。 #### XML 处理技术 **7.26 Tip:DTD 的语法细节** - **内容**: - 元素定义 - 属性定义...