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. 登录验证码实现(Captcha)

    登录验证码 登录验证是一般系统都会有的功能,验证的方式也多种多样,比如输入式验证码,拖动式验证条,拖动式验证拼图等等. 我们这里先实现常规的输入验证码的方式,右边显示验证码图片,点击可刷新,左边输入验 ...

  2. 原生js(form)验证,可以借鉴下思路,应用到工作中

    我在工作中时常使用form验证,在目前的公司做的表单验证用的angular的form组件,对于一个有追求的前端,或者应用在移动端写个form验证,引入angular或者jquery组件等验证,难免显得 ...

  3. 实现django admin后台到xadmin后台的转变

    虽然不做前端,还是喜欢好看的东西~.~ 之前同事估计也是功能实现没空管这个后台,前段时间闲的,稍微改了下外貌,前后对比下: Python3.5+Django1.9.7+Xadmin0.6.1 步骤如下 ...

  4. MySQL mysql server与存储引擎

    mysql server系统架构 逻辑模块组成: mysql逻辑模块可以分为两层架构,第一层是sql layer主要包括权限判断.sql解析.执行计划优化.query cache的处理等:第二层是存储 ...

  5. day17 面向对象-成员

    今日主要学习了: 1 .成员 2. 变量 3. 方法 4.属性 5.私有 1. 成员 在类中你能写的所有内容都是成员 2 .变量 1) 实例变量: 昨天写的就是实例变量 ,由对象去访问的变量 . cl ...

  6. C++各种类继承关系的内存布局

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  7. unordered_map/unordered_set & unordered_multimap/unordered_multiset非关联容器

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  8. 3.2 Bochs

    Bochs 工具 bochs: bochs ubuntu安装配置Bochs 安装bochs sudo apt-get install bochs bochs-x 创建工程目录 创建工程目录并进入 新建 ...

  9. php安装及配置笔记

    windows下启动php-cgi方式为:php-cgi.exe -b 127.0.0.1:9000 -c php.ini(也可以是绝对路径). 安装XDebug支持,最基本的配置参数为: [xdeb ...

  10. linux 创建安装redis服务

    1.找下redis的官方的下载地址:http://download.redis.io/releases/redis-3.2.8.tar.gz  有最新的就下载最新 先下载解压跟安装 wget http ...