类在何时加载和初始化

本文由 ImportNew - 刘志军 翻译自 Javarevisited。欢迎加入翻译小组。转载请见文末要求。html

理解类在JVM中何时被加载和初始化是Java编程语言中的基础概念,正由于有了Java语言规范,咱们才能够清晰的记录和解释这个问题,可是不少Java程序员仍然不知道何时类被加载,何时类被初始化,类加载和初始化好像让人很困惑,对初学者难以理解,在这篇教程中咱们将看看类加载何时发生,类和接口是如何被初始化的,我并不会拘泥于类加载器的细节或者说类加载器的工做方式。仅仅使这篇文章更加专一和简结。java

类何时加载程序员

类的加载是经过类加载器(Classloader)完成的,它既能够是饿汉式[eagerly load](只要有其它类引用了它就加载)加载类,也能够是懒加载[lazy load](等到类初始化发生的时候才加载)。不过我相信这跟不一样的JVM实现有关,然而他又是受JLS保证的(当有静态初始化需求的时候才被加载)。面试

类何时初始化

加载完类后,类的初始化就会发生,意味着它会初始化全部类静态成员,如下状况一个类被初始化:编程

  1. 实例经过使用new()关键字建立或者使用class.forName()反射,但它有可能致使ClassNotFoundException。
  2. 类的静态方法被调用
  3. 类的静态域被赋值
  4. 静态域被访问,并且它不是常量
  5. 在顶层类中执行assert语句

反射一样可使类初始化,好比java.lang.reflect包下面的某些方法,JLS严格的说明:一个类不会被任何除以上以外的缘由初始化。编程语言

类是如何被初始化的

如今咱们知道何时触发类的初始化了,他精确地写在Java语言规范中。但了解清楚 域(fields,静态的仍是非静态的)、块(block静态的仍是非静态的)、不一样类(子类和超类)和不一样的接口(子接口,实现类和超接口)的初始化顺序也很重要类。事实上不少核心Java面试题和SCJP问题都是基于这些概念,下面是类初始化的一些规则:this

  1. 类从顶至底的顺序初始化,因此声明在顶部的字段的早于底部的字段初始化
  2. 超类早于子类和衍生类的初始化
  3. 若是类的初始化是因为访问静态域而触发,那么只有声明静态域的类才被初始化,而不会触发超类的初始化或者子类的初始化即便静态域被子类或子接口或者它的实现类所引用。
  4. 接口初始化不会致使父接口的初始化。
  5. 静态域的初始化是在类的静态初始化期间,非静态域的初始化时在类的实例建立期间。这意味这静态域初始化在非静态域以前。
  6. 非静态域经过构造器初始化,子类在作任何初始化以前构造器会隐含地调用父类的构造器,他保证了非静态或实例变量(父类)初始化早于子类

初始化例子spa

这是一个有关类被初始化的例子,你能够看到哪一个类被初始化翻译

1code

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. 没使用的类根本不会被初始化,由于他没有被使用

再来看一个例子:

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

分析:

  1. 这里的初始化发生是由于有静态域被访问,并且不一个编译时常量。若是声明的”familyName”是使用final关键字修饰的编译时常量使用(就是上面的注释代码块部分)超类的初始化就不会发生。
  2. 尽管静态与被子类所引用可是也仅仅是超类被初始化

还有另一个例子与接口相关的,JLS清晰地解释子接口的初始化不会触发父接口的初始化。强烈推荐阅读JLS14.4理解类加载和初始化细节。以上全部就是有关类被初始化和加载的所有内容。

原文连接: Javarevisited 翻译: ImportNew.com - 刘志军
译文连接: http://www.importnew.com/6579.html
[ 转载请保留原文出处、译者和译文连接。]

相关文章
相关标签/搜索