java虚拟机规范虽然没有强制性约束在什么时候开始类加载过程,但是对于类的初始化,虚拟机规范则严格规定了有且只有四种情况必须立即对类进行初始化,遇到new、getStatic、putStatic或invokeStatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。
生成这4条指令最常见的java代码场景是:

1)使用new关键字实例化对象

2)读取一个类的静态字段(被final修饰、已在编译期把结果放在常量池的静态字段除外)

3)设置一个类的静态字段(被final修饰、已在编译期把结果放在常量池的静态字段除外)

4)调用一个类的静态方法

验证:

1)当类被初始化时,其静态代码块会执行。

class ClassLoadTime{

  static{

    System.out.println("ClassLoadTime类初始化时就会被执行!");

  }

  public ClassLoadTime(){

    System.out.println("ClassLoadTime构造函数!");

  }

}

class ClassLoadDemo{

  public static void main(String[] args){

    ClassLoadTime  clt = new ClassLoadTime();

  }

}

输出结果:

ClassLoadTime类初始化时就会被执行!

ClassLoadTime构造函数!


2) 读取一个类的静态字段(被final修饰、已在编译期把结果放在常量池的静态字段除外)

class ClassLoadTime{

  static{

    System.out.println("ClassLoadTime类初始化时就会被执行!");

  }

  public static int max = 200; (防止测试类和此类不在一个包,使用public修饰符)

  public ClassLoadTime(){

    System.out.println("ClassLoadTime构造函数!");

  }

}

class ClassLoadDemo{

  public static void main(String[] args){

    int  value = ClassLoadTime.max;

    System.out.println(value);

  }

}

输出:

ClassLoadTime类初始化时就会被执行!

200


3)设置一个类的静态字段(被final修饰、已在编译期把结果放在常量池的静态字段除外)

class ClassLoadTime{

  static{

    System.out.println("ClassLoadTime类初始化时就会被执行!");

  }

  public static int max = 200; (防止测试类和此类不在一个包,使用public修饰符)

  public ClassLoadTime(){

    System.out.println("ClassLoadTime构造函数!");

  }

}

class ClassLoadDemo{

  public static void main(String[] args){

      ClassLoadTime.max = 100;

  }

}

输出:

ClassLoadTime类初始化时就会被执行!


4)调用一个类的静态方法

class ClassLoadTime{

  static{

    System.out.println("ClassLoadTime类初始化时就会被执行!");

  }

  public static int max = 200; (防止测试类和此类不在一个包,使用public修饰符)

  public ClassLoadTime(){

    System.out.println("ClassLoadTime构造函数!");

  }

  public static void method(){

    System.out.println("静态方法的调用!");

  }

}

class ClassLoadDemo{

  public static void main(String[] args){

      ClassLoadTime.method();

  }

}

输出:

ClassLoadTime类初始化时就会被执行!

静态方法的调用!


被final修饰静态字段在操作使用时,不会使类进行初始化,因为在编译期已经将此常量放在常量池。

测试:

class ClassLoadTime{

  static{

    System.out.println("ClassLoadTime类初始化时就会被执行!");

  }

  public static final int MIN = 10; (防止测试类和此类不在一个包,使用public修饰符)

}

class ClassLoadDemo{

  public static void main(String[] args){

   System.out.println(ClassLoadTime.MIN);

  }

}

输出:

10


子类调用或者设置父类的静态字段或者调用父类的静态方法时仅仅初始化父类,而不初始化子类。同样读取final修饰的常量不会进行类的初始化。

class Fu{

  public static int value = 20;

  static{

    System.out.println("父类进行了类的初始化!");

  }

}

class Zi{

  static{

    System.out.println("子类进行了类的初始化!");

  }

}

class LoadDemo{

  public static void main(String[] args){

    System.out.println(Zi.value);    

  }

}

输出:

父类进行了类的初始化!

20


java类中各种成员的初始化时机,此处不一一测试:

类变量(静态变量)、实例变量(非静态变量)、静态代码块、非静态代码块 的初始化时机:
* 由 static 关键字修饰的(如:类变量[静态变量]、静态代码块)将在类被初始化创建实例对象之前被初始化,而且是按顺序从上到下依次被执行;

public static int value =34;

static{

  System.out.println("静态代码块!");

 }

 public 类名(){

  System.out.println("构造函数!");

 }

一旦这样写,在类被初始化创建实例对象之前会先初始化静态字段value,然后执行静态代码块,当实例化对象时会执行构造方法中的代码
* 没有 static 关键字修饰的(如:实例变量[非静态变量]、非静态代码块)初始化实际上是会被提取到类的构造器中被执行的,但是会比类构造器中的
   代码块优先执行到,其也是按顺序从上到下依次被执行。

public int value =34;

{

  System.out.println("非静态代码块!");

 }

 public 类名(){

  System.out.println("构造函数!");

 }

在使用构造函数实例化一个对象时,会先初始化value,然后执行非静态代码块,最后执行构造方法里面的代码。

*在存在父类的时候,调用子类的构造时,会先调用父类的默认构造(空参构造),进行父类的初始化。

java中类加载时机的更多相关文章

  1. java 中类加载器

    jar 运行过程和类加载机制有关,而类加载机制又和我们自定义的类加载器有关,现在我们先来了解一下双亲委派模式. java 中类加载器分为三个: BootstrapClassLoader 负责加载 ${ ...

  2. ClassLoader Java中类加载出现在哪个阶段,编译期和运行期? 类加载和类装载是一样的吗

    1.ClassLoader Java中类加载出现在哪个阶段,编译期和运行期? 类加载和类装载是一样的吗? :当然是运行期间啊,我自己有个理解误区,改正后如下:编译期间编译器是不去加载类的,只负责编译而 ...

  3. java中类加载顺序(深入Java)

    未涉及虚拟机 0.<init>与<clinit>的区别 1.类的加载过程 2.类的使用方式 3.类的加载来源 4.重载之泛型参数不同可以吗 5.参考 引子 记得上次中秋一哥们写 ...

  4. Java中类加载和反射技术实例

    我们知道一个对象在运行时有两种类型,一个是编译类型,一个是运行时类型.在程序运行时,往往是需要发现类和对象的真实的信息的.那么如何获的这种信息呢? 其一,如果我们在编译和运行时都知道类型的具体信息,这 ...

  5. java中类加载的全过程及内存图分析

    类加载机制: jvm把class文件加载到内存,并对数据进行校验.解析和初始化,最终形成jvm可以直接使用的java类型的过程. (1)加载 将class文件字节码内容加载到内存中,并将这些静态数据转 ...

  6. Java中类加载的过程

    类加载过程 这里的加载过程是严格按照加载开始顺序进行的,注意是加载开始而不是加载完成.也就是有可能会有两个或几个阶段是同时进行的. 比如下面提到的验证过程中的符号引用验证是在解析阶段开始之后进行. 加 ...

  7. Java中类加载过程和对象创建过程

    类加载过程: 1, JVM会先去方法区中找有没有相应类的.class存在.如果有,就直接使用:如果没有,则把相关类的.class加载到方法区 2, 在.class加载到方法区时,会分为两部分加载:先加 ...

  8. java中初始化时机和顺序呢

    class Pupil{ Pupil(int age){ System.out.println("Pupil:"+age); } } class Teacher{ Pupil p1 ...

  9. 从一道面试题来认识java类加载时机与过程

    说明:本文的内容是看了<深入理解Java虚拟机:JVM高级特性与最佳实践>后为加印象和理解,便记录了重要的内容. 1  开门见山 以前曾经看到过一个java的面试题,当时觉得此题很简单,可 ...

随机推荐

  1. 序列(SEQUENCE)

    序列(SEQUENCE)是序列号生成器,可以为表中的行自动生成序列号,产生一组等间隔的数值(类型为数字).其主要的用途是生成表的主键值,可以在插入语句中引用,也可以通过查询检查当前值,或使序列增至下一 ...

  2. python3 爬取简书30日热门,同时存储到txt与mongodb中

    初学python,记录学习过程. 新上榜,七日热门等同理. 此次主要为了学习python中对mongodb的操作,顺便巩固requests与BeautifulSoup. 点击,得到URL https: ...

  3. Linux学习 :移植U-boot_2012.04.01到JZ2440开发板

    一.下载U-boot源码:ftp://ftp.denx.de/pub/u-boot/ 二.uboot的启动过程: 部分硬件初始化——>加载完整uboot到RAM——>跳转到第二阶段入口开始 ...

  4. 用户登录页面——jdbc

    登录页面程序login.jsp <%@ page language="java" import="java.util.*" pageEncoding=&q ...

  5. maven 打包前 Junit 测试

    1. 在需要打包前测试的项目中添加依赖 <dependency> <groupId>junit</groupId> <artifactId>junit& ...

  6. mybatis 异常 There is no getter for property named 'bizId' in 'class java.lang.Long'

    mybatis 异常 There is no getter for property named 'bizId' in 'class java.lang.Long' 当使用mybatis进行传参的时候 ...

  7. HTML5触摸事件(touchstart、touchmove和touchend)

      HTML5中新添加了很多事件,但是由于他们的兼容问题不是很理想,应用实战性不是太强,所以在这里基本省略,咱们只分享应用广泛兼容不错的事件,日后随着兼容情况提升以后再陆续添加分享.今天为大家介绍的事 ...

  8. 字典和json 的区别 和转换

    前言:字典和json非常像.接下来比较一下两者的异同 先看一下字典的写法: a = {', ', ' } 再看一下json的写法: { "studentInfo": { " ...

  9. L300 3月英语课下

    重音 句中的实词(内容词)要被重读,读得重.长一点.句中的虚词(功能词)要被轻读或弱读,读得轻.短一点口语交流中,当虚词的在句中起到重要的表意作用时,会被重读. 连读 连读:把一个单词的尾音同下一个单 ...

  10. WIFI探针 搞定