一、误区:简单认为JAVA静态代码块在类被加载时就会自动执行。证错如下:

  1. class MyClass1 {
  2. static {//静态块
  3. System.out.println("static block ");
  4. }
  5. }
  6. public class Main {
  7. Class[] classArray = {
  8. MyClass1.class//这样引用该类,必然需要将该类加载到虚拟机中
  9. };
  10. public static void main(String[] args){
  11. System.out.println("hello word");
  12. }
  13. }

执行结果:并没有输出" static bolck"

二、正解:static块真正的执行时机。如果了解JVM原理,我们知道,一个类的运行分为以下步骤:

  1. 装载
  2. 连接
  3. 初始化

其中装载阶段又三个基本动作组成:

  1. 通过类型的完全限定名,产生一个代表该类型的二进制数据流
  2. 解析这个二进制数据流为方法区内的内部数据结
  3. 构创建一个表示该类型的java.lang.Class类的实例

另外如果一个类装载器在预先装载的时遇到缺失或错误的class文件,它需要等到程序首次主动使用该类时才报告错误。

连接阶段又分为三部分:

  1. 验证,确认类型符合Java语言的语义,检查各个类之间的二进制兼容性(比如final的类不用拥有子类等),另外还需要进行符号引用的验证。
  2. 准备,Java虚拟机为类变量分配内存,设置默认初始值。
  3. 解析(可选的) ,在类型的常量池中寻找类,接口,字段和方法的符号引用,把这些符号引用替换成直接引用的过程。

  当一个类被主动使用时,Java虚拟就会对其初始化,如下六种情况为主动使用:

  1. 当创建某个类的新实例时(如通过new或者反射,克隆,反序列化等)
  2. 当调用某个类的静态方法时
  3. 当使用某个类或接口的静态字段时
  4. 当调用Java API中的某些反射方法时,比如类Class中的方法,或者java.lang.reflect中的类的方法时
  5. 当初始化某个子类时
  6. 当虚拟机启动某个被标明为启动类的类(即包含main方法的那个类)

Java编译器会收集所有的类变量初始化语句和类型的静态初始化器,将这些放到一个特殊的方法中:clinit。

 
实际上,static块的执行发生在“初始化”的阶段。初始化阶段,jvm主要完成对静态变量的初始化,静态块执行等工作。

下面我们看看执行static块的几种情况:

1、第一次new A()的过程会打印"";因为这个过程包括了初始化

2、第一次Class.forName("A")的过程会打印"";因为这个过程相当于Class.forName("A",true,this.getClass().getClassLoader());

3、第一次Class.forName("A",false,this.getClass().getClassLoader())的过程则不会打印""。因为false指明了装载类的过程中,不进行初始化。不初始化则不会执行static块。

参考资料:《深入Java虚拟机》

转自http://blog.csdn.net/berber78/article/details/46472789

java的static块执行时机<转>的更多相关文章

  1. Java中static块执行时机

    Java中static块执行时机 演示例子 在使用static进行初始化的操作,怎么也执行不了!代码如下: public class StaticDemo { public static final ...

  2. java的static块执行时机

    一.误区:简单认为JAVA静态代码块在类被加载时就会自动执行.证错如下: class MyClass1 { static {//静态块 System.out.println("static  ...

  3. java static代码块执行时机

    之前一直认为static块是在class load的时候执行,今天在验证Spring初始化Context loader的时候,发现bean的static块并没有执行. Java代码: 1 Class ...

  4. java finally块执行时机分析

    java里 finally 关键字通常与try catch块一起使用.用来在方法结束前或发生异常时做一些资源释放的操作.最近也看到网上有一些讨论try catch finally关键词执行的顺序的文章 ...

  5. java的static块及相关内容

    原文地址:http://blog.csdn.NET/lubiaopan/article/details/4802430     感谢原作者! static{}(即static块),会在类被加载的时候执 ...

  6. java static{}块

    java中static{}块只有在类加载是才会被调用. 这说明:static只有可能被调用一次. 原因:首先理解什么是类加载,区分类加载和申明对象的区别. public class StaticTes ...

  7. [java基础]java中static关键字

    1.static概念 static是静态修饰符,什么叫静态修饰符呢?大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序 ...

  8. java中static作用详解

    static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何 ...

  9. Java中static关键字的作用和用法详细介绍

    static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何 ...

随机推荐

  1. 【LeetCode】41. First Missing Positive (3 solutions)

    First Missing Positive Given an unsorted integer array, find the first missing positive integer. For ...

  2. 自定义类似于listView中Item背景

    方法一. drawable/listitem_bk.xml <?xml version="1.0" encoding="utf-8" ?> < ...

  3. Redis客户端

    1.自带的: Redis-cli 2.redis-desktop-manager-0.7.9.809  是一个图形化客户端 但是不支持集群  **由于linux防火墙默认开启,redis的服务端口63 ...

  4. oc 异常处理

    #import <UIKit/UIKit.h> #import "AppDelegate.h" int main(int argc, char * argv[]) { ...

  5. PLSQL_标准游标类型的解析(概念)

    2014-06-02 Created By BaoXinjian

  6. slub分配器

    Linux的物理内存管理采用了以页为单位的buddy system(伙伴系统),但是很多情况下,内核仅仅需要一个较小的对象空间,而且这些小块的空间对于不同对象又是变化的.不可预测的,所以需要一种类似用 ...

  7. tomcat配置外部静态资源映射路径

    一.背景 1.有一个录音软件每天生成很多新的录音文件. 2.现在想通过一个WEB项目页面下载这些录音文件. 3.很显然这些录音文件放在WEB项目下不是很合适(WEB项目更新是个大麻烦,海量的录音文件要 ...

  8. 【JEECG_3.7.1】列表多表头的设计

    先看下多表头的设计: 在这个多表头的表单当中,我们可以按照从上到下和从左往右的划分方式,将表头划分成三行十列,分别是: 列表标签 人员信息.部门信息.工资.入职状态.创建日期.操作 名称.年龄.性别. ...

  9. How to set JAVA environment variables in Linux or CentOS

    How to set JAVA environment variables JAVA_HOME and PATH in Linux After installing new java (jdk or ...

  10. MySql(七):MySQL性能调优——锁定机制与锁优化分析

    针对多线程的并发访问,任何一个数据库都有其锁定机制,它的优劣直接关系着数据的一致完整性与数据库系统的高并发处理性能.锁定机制也因此成了各种数据库的核心技术之一.不同数据库存储引擎的锁定机制是不同的,本 ...