标签:阅读 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 initialized static block of Sub class is initialized in Java non static blocks in super class is initialized non static blocks in sub class is initialized false |
从上面结果可以看出:
再来看一个例子:
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 initialized Lawson |
分析:
还有另外一个例子与接口相关的,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