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 ...
【反射】反射中,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 的语法细节** - **内容**: - 元素定义 - 属性定义...