zoukankan      html  css  js  c++  java
  • static语句块的执行时间

    
    

    package utfTest;

    
    

    public class Test01 {
    public static void main(String[] args) {
    //Person.show();
    System.out.println("p还没有初始化");
    Class cls=Person.class;
    System.out.println("执行了语句:Class cls=Person.class;不知道static语句在这条语句之前是否有输出");
    Person p = new Person();
    System.out.println("p刚刚被初始化,这里输出是用来验证static语句块是在哪里被输出的");
    p.setName("小明");
    p.setAge(18);
    Person p1 = p;
    p1.setAge(10);
    p.setName("小邹");
    System.out.println("p1创建了");
    System.out.println(p.getName()+" "+p.getAge());
    System.out.println(p1.getName()+" "+p1.getAge());
    }
    }

    
    

    class Person{
    int age;
    String name;
    static int id=0;
    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }

    static{
    System.out.println("这里输出的是静态代码块");//这条语句在编译阶段执行,只会被执行一次
    System.out.println("id="+id);
    }
    static public void show(){
    System.out.println("这是static方法,我是在什么时候被输出的呢?");
    }
    }

     

    运行结果是:

    static语句块是在初始化阶段被执行的,而不是类加载阶段。

    如果在main方法的开头添加了代码块:Person.show();那么运行结果是:

    以下转载自:https://blog.csdn.net/berber78/article/details/46472789

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

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

    执行结果:并没有输出" 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虚拟机》

    --------------------- 本文来自 berber78 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/berber78/article/details/46472789?utm_source=copy 

  • 相关阅读:
    安卓小助手
    位图切割器&位图裁剪器
    OAuth2.0 的简介
    多账户的统一登录方案
    常用的一些SQL语句
    SQL语句的优化
    SpringCloud简介与5大常用组件
    数据库为什么需要锁机制?有哪些锁机制?
    高并发下如何优化能避免服务器压力过大?
    Spring MVC 简介
  • 原文地址:https://www.cnblogs.com/liaoxiaolao/p/9759700.html
Copyright © 2011-2022 走看看