Java动态性: 类加载时的延迟初始化
2011-10-27 21:44
316 查看
Java类加载的延迟初始化
SEP 8TH, 2013 | COMMENTS《Java 类的装载、链接和初始化》中提到,链接的最后一步是解析,即对符号引用的解析。但这不是必须的,可以等到相应的符号引用第一次使用时再解析。
而类的初始化是在链接之后的(注意了,根据不同 JVM 有不同的实现方式,在类初始化的时候,可能已经完成了所有的符号引用的解析,也可能没有),本文所写的就是类的初始化的时机问题。
Java 类的动态加载机制规定,在类被主动使用(active use)之前,必须已经完成类的初始化。既然有主动调用,那么就有被动调用了。这两者有哪些区别呢?
下面列出所有主动使用的情况,用以区分两者:
1.创造该类的一个新的实例
2.调用这个类中的静态方法
3.获取类或者接口中的非常量的静态变量
4.利用反射调用方法
5.初始化该类的某子类
6.被制定为 JVM 开始运行时必须初始化的类
注意,3 中为何是“非常量的静态变量”。如果是常量,即声明为 final 的话,并不会出现对类的构造,虽然调用时有类名出现,但实际调用会直接使用常量,绕过了类的限制(详情见相关常量池和运行时常量池的知识)。
只有当一个非常量的静态变量被显示的在类或接口中声明时,它的调用才属于主动调用。对于父类中某非常量静态变量的调用属于被动使用(positive use)。
如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | [code]public class Parent { static int i = 10 ; static{ System.out.println("Parent initiate"); } public static void func(){ System.out.println("func"); } } public class Son extends Parent{ static{ System.out.println("Son initiate"); } } public class Test { static{ System.out.println("Test initiate"); } public static void main(String[] args){ System.out.println(Son.i); Son.func(); } } |
1 2 3 4 | [code]Test initiate Parent initiate 10 func |
由此可见,一般的,我们在某个类中定义了其他类的成员变量引用,只要该变量没有 new 出一个新的对象,则 JVM 也不会初始化这个类,类此时只是被加载了而已,而没有链接和初始化。
原文地址:http://biaobiaoqi.github.com/blog/2013/09/08/late-initialising-in-java/
版权声明:自由转载-非商用-非衍生-保持署名| Creative Commons BY-NC-ND 3.0
相关文章推荐
- Java动态性: 类加载时的延迟初始化
- Java 类加载与初始化
- Java类的加载,链接,初始化
- JAVA 类的加载与初始化
- java初始化的加载顺序-----我的理解
- Java系列笔记(1) - Java 类加载与初始化
- Java系列笔记 - Java 类加载与初始化
- 关于java从编译成class文件到加载再到初始化过程解析
- java Hibernate延迟加载
- 转 java 四种实现延迟加载的方法
- Java深度历险(二)——Java类的加载、链接和初始化
- java的继承关系中对象的加载和初始化顺序
- 从头认识java-6.7 初始化与类的加载
- Java深度历险(二)——Java类的加载、链接和初始化
- java类的加载、链接和初始化(摘自infoq的java深度历险)
- Spring学习--懒加载(延迟初始化Bean)与自动装配
- Java类加载及变量初始化过程
- java并发线程安全,延迟初始化中的竞态条件。
- Java深度历险(二)——Java类的加载、链接和初始化
- java深入学习四之类的加载,连接和初始化