标签:阅读 load throw 译文 虚拟机 time target imp 推荐
类的加载是通过类加载器(Classloader)完成的,它既可以是饿汉式[eagerly load](只要有其它类引用了它就加载)加载类,也可以是懒加载[lazy load](等到类初始化发生的时候才加载)。不过我相信这跟不同的JVM实现有关,然而他又是受JLS保证的(当有静态初始化需求的时候才被加载)。
加载完类后,类的初始化就会发生,意味着它会初始化所有类静态成员,以下情况一个类被初始化:
反射同样可以使类初始化,比如java.lang.reflect包下面的某些方法,JLS严格的说明:一个类不会被任何除以上之外的原因初始化。
现在我们知道什么时候触发类的初始化了,他精确地写在Java语言规范中。但了解清楚 域(fields,静态的还是非静态的)、块(block静态的还是非静态的)、不同类(子类和超类)和不同的接口(子接口,实现类和超接口)的初始化顺序也很重要类。事实上很多核心Java面试题和SCJP问题都是基于这些概念,下面是类初始化的一些规则:
这是一个有关类被初始化的例子,你可以看到哪个类被初始化
|
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
31
32
33
34
35
36
37
38
39
40
41
42
|
/** * Java program to demonstrate class loading and initialization in Java. */public class ClassInitializationTest { public static void main(String args[]) throws InterruptedException { NotUsed o = null; //this class is not used, should not be initialized Child t = new Child(); //initializing sub class, should trigger super class initialization System.out.println((Object)o == (Object)t); }}/** * Super class to demonstrate that Super class is loaded and initialized before Subclass. */class Parent { static { System.out.println("static block of Super class is initialized"); } {System.out.println("non static blocks in super class is initialized");}}/** * Java class which is not used in this program, consequently not loaded by JVM */class NotUsed { static { System.out.println("NotUsed Class is initialized "); }}/** * Sub class of Parent, demonstrate when exactly sub class loading and initialization occurs. */class Child extends Parent { static { System.out.println("static block of Sub class is initialized in Java "); } {System.out.println("non static blocks in sub class is initialized");}}Output:static block of Super class is initializedstatic block of Sub class is initialized in Javanon static blocks in super class is initializednon static blocks in sub class is initializedfalse |
从上面结果可以看出:
再来看一个例子:
|
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
|
/** * Another Java program example to demonstrate class initialization and loading in Java. */public class ClassInitializationTest { public static void main(String args[]) throws InterruptedException { //accessing static field of Parent through child, should only initialize Parent System.out.println(Child.familyName); }}class Parent { //compile time constant, accessing this will not trigger class initialization //protected static final String familyName = "Lawson"; protected static String familyName = "Lawson"; static { System.out.println("static block of Super class is initialized"); } {System.out.println("non static blocks in super class is initialized");}}Output:static block of Super class is initializedLawson |
分析:
还有另外一个例子与接口相关的,JLS清晰地解释子接口的初始化不会触发父接口的初始化。强烈推荐阅读JLS14.4理解类加载和初始化细节。以上所有就是有关类被初始化和加载的全部内容。
对于类的加载顺序,网上有详细的,我这里只说一些简单的:
首先需要用到一个类的时候,虚拟机会从classpath读取此类的代码,到内存的类的代码存储区,然后对于每一个静态字段开辟一个存储区,再存储方法的代码。接着初始化类,所有的静态成员按照顺序初始化(按代码声明顺序从上到下开始),当需要加载其他类的时候加载其他的类。然后完成初始化供虚拟机使用。
当实例化一个类的时候,如果需要加载的话,会按照上面的顺序加载,然后在内存中分配所有实例字段的空间,接着调用构造函数,其中构造函数会(显示或隐式的)调用父类构造函数(此过程向上递归),然后执行剩下的构造代码。最后返回实例化的对象的引用返回构造函数。
类的代码在初次使用时才会加载
这通常是指加载发生于创建类的第一个对象时,但是当访问static域或static 方法时,也会发生加载
原文链接: Javarevisited 翻译: ImportNew.com - 刘志军
译文链接: http://www.importnew.com/6579.html
标签:阅读 load throw 译文 虚拟机 time target imp 推荐
原文地址:http://www.cnblogs.com/nextgg/p/7653687.html