zoukankan      html  css  js  c++  java
  • Java的静态代码块是否会在类被加载时自动执行?

    JAVA静态代码块会在类被加载时自动执行?

    一、先看Java静态方法,静态变量

    http://www.cnblogs.com/winterfells/p/7906078.html

    静态代码块

    在类中,可以将某一块代码声明为静态的,这样的程序块叫静态初始化段。静态代码块的一般形式如下:

    static {
        语句序列
    }
    public class staticBlock{
    
            //定义一个普通的main()方法
    
            public static void main(String args[]){
    
            System.out.println("This is main method."); 
    
           }
    
          //定义一个静态代码块
    
         static{
    
             System.out.println("This is static block.");
    
             int stVar = 0;   //这是一个局部变量,只在本块内有效
    
          }
    
    }

    编译通过后,用java命令加载本程序,会得到如下输出:

    This is static block.

    This is main method.

    从以上输出结果中可以看出,静态代码块甚至在main方法之前就被执行。在main()方法中可以完成的任务在静态代码块中都可以完成。但是二者在执行上仍然有一些区别,main方法是整个程序启动的入口,而静态代码块是存在于某个类中的一个过程。

    那是不是只要类被加载了就一定会执行静态代码块?

    二、再看JVM类加载的过程

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

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

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

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

        连接阶段又分为三部分:

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

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

      1. 遇到new, getstatic, putstatic 或者 invokestatic 4条字节码指令时,如果类没有进行过初始化,则需要先进行初始化。这些场景包括:使用new关键字实例化对象,读取或者设置一个类的静态字段以及调用一个类的静态方法的时候。

      2. 使用java.lang.reflect包的方法进行反射调用的时候,如果类没有初始化,需要进行初始化。

      3. 当初始化一个类的时候发现其父类还没有初始化,需要对父类进行初始化。

      4. JVM启动时,用户指定的包含main方法的那个类,需要首先进行初始化。

      5. JDK1.7中动态语言的支持,解析java.lang.invoke.MethodHandle的结果为REF_getStatic, REF_putStatic, REF_invokeStatic方法的句柄时,对应的类没有初始化的时候。

    实际上,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块。

    再看这个例子

    class MyClass1 {
        static {//静态块
            System.out.println("static block ");
        }
    }
    public class Main {
    
        Class[] classArray = {
                MyClass1.class//这样引用该类,必然需要将该类加载到虚拟机中,(反射机制)
        };
        public static void main(String[] args){
            System.out.println("hello word");
        }
    
    }

    结果:

    hello world

    所以结论是不初始化则不会执行static块。

    参考:《深入理解java虚拟机》

    http://blog.csdn.net/jiese1990/article/details/40154329

    http://www.cnblogs.com/ivanfu/archive/2012/02/12/2347817.html

  • 相关阅读:
    面试可能遇到的关联式容器(map、set等)相关问题
    C++学习 STL组件之vector部分总结
    C++ 菱形虚拟继承 与 指针偏移问题
    C++ 关键字 explicit 的使用
    C++ sort()排序函数用法
    C++ 字符流 stringstream
    C/C++ 每日一题
    C/C++ 超长正整数相加
    C++ 二叉搜索树原理及其实现
    Tomcat安装
  • 原文地址:https://www.cnblogs.com/winterfells/p/7908189.html
Copyright © 2011-2022 走看看