zoukankan      html  css  js  c++  java
  • 非静态代码块的编译机制

    今天遇到一个关于静态代码块和非静态代码块执行的问题。先看如下程序。

    package com.zpj.classload;
    
    /**
     * @author Perkins Zhu
     * @version 2017年1月17日 下午8:07:34
     */
    public class StaticClass {
    
        static int A = 5;
        static {
            A = 6;
            System.out.println("Static code block----" + A);
        }
        {
            A = 8;
            System.out.println("Non Static code block----" + A);
        }
    
        StaticClass() {
            this(A);
            A = 3;
            System.out.println("Construction method----" + A);
        }
    
        StaticClass(int i) {
            A = i;
            System.out.println("Construction method with parameters----" + A);
        }
    
        public static void main(String[] args) {
            StaticClass sc = new StaticClass();
        }
    }

     程序运行结果如下:

    Static code block----6
    Non Static code block----8
    Construction method with parameters----6
    Construction method----3

     对于前两行的输出倒是没什么疑问,加载的时候先加载静态代码块然后加载非静态代码块,静态代码块只在加载类的时候加载一次,而非静态代码块在每次new一个对象的时候进行加载。可第三行的那个A明明已经赋值为8了,可为什么还输出一个6呢?

    于是打断点走了一次发现,在执行到this(A);的时候,程序直接掉到非静态代码块中进行执行。执行完非静态代码块之后才继续纸箱带参构造方法。怪了!!! 

    找不到原因,便决定生成class文件然后反编译一下看看反编译之后的代码如何。这一反编译便找到了原因,看反编译之后的代码:

    import java.io.PrintStream;
    
    public class StaticClass
    {
      static int A = 5;
      
      static { A = 6;
        System.out.println("Static code block----" + A);
      }
      
      StaticClass()
      {
        this(A);
        A = 3;
        System.out.println("Construction method----" + A);
      }
      
      StaticClass(int paramInt)
      {
          //注意如下两行,原来的非静态代码块中的内容被加载到了含参构造器中
        A = 8;
        System.out.println("Non Static code block----" + A);
        
        A = paramInt;
        System.out.println("Construction method with parameters----" + A);
      }
      
      public static void main(String[] paramArrayOfString) {
        StaticClass localStaticClass = new StaticClass();
      }
    }

     非静态代码块消失了,被加载到含参构造器中。这便解释了为什么会出现上面的这种情况,同时也解释了为何非静态代码块会在每次new对象的时候都要加载一次。

     那么,问题又来了。为什么非静态代码块会被加载到含参构造器中而没有加载到不含参构造器中呢?

     下面又重新更改代码:去掉含参构造器之后

    package com.zpj.classload;
    
    /**
     * @author Perkins Zhu
     * @version 2017年1月17日 下午8:07:34
     */
    public class StaticClass {
    
        static int A = 5;
        static {
            A = 6;
            System.out.println("Static code block----" + A);
        }
        {
            A = 8;
            System.out.println("Non Static code block----" + A);
        }
    
        StaticClass() {
            A = 3;
            System.out.println("Construction method----" + A);
        }
    
        public static void main(String[] args) {
            StaticClass sc = new StaticClass();
        }
    }

    反编译结果

    import java.io.PrintStream;
    
    public class StaticClass { static int A = 5;
      
      static { A = 6;
        System.out.println("Static code block----" + A);
      }
      
      StaticClass() { 
      A
    = 8; System.out.println("Non Static code block----" + A); A = 3; System.out.println("Construction method----" + A); } public static void main(String[] paramArrayOfString) { StaticClass localStaticClass = new StaticClass(); } }

    去掉不含参构造方法

    package com.zpj.classload;
    
    /**
     * @author Perkins Zhu
     * @version 2017年1月17日 下午8:07:34
     */
    public class StaticClass {
    
        static int A = 5;
        static {
            A = 6;
            System.out.println("Static code block----" + A);
        }
        {
            A = 8;
            System.out.println("Non Static code block----" + A);
        }
    
        StaticClass(int i) {
            A = i;
            System.out.println("Construction method with parameters----" + A);
        }
    
        public static void main(String[] args) {
            StaticClass sc = new StaticClass(2);
        }
    }

    反编译之后如下:

    import java.io.PrintStream;
    
    public class StaticClass
    {
      static int A = 5;
      
      static { A = 6;
        System.out.println("Static code block----" + A);
      }
      
      StaticClass(int paramInt) { A = 8;
        System.out.println("Non Static code block----" + A);
        
        A = paramInt;
        System.out.println("Construction method with parameters----" + A);
      }
      
      public static void main(String[] paramArrayOfString) {
        StaticClass localStaticClass = new StaticClass(2);
      }
    }

     再添加一个两个参数的构造器

    package com.zpj.classload;
    
    /**
     * @author Perkins Zhu
     * @version 2017年1月17日 下午8:07:34
     */
    public class StaticClass {
    
        static int A = 5;
        static {
            A = 6;
            System.out.println("Static code block----" + A);
        }
        {
            A = 8;
            System.out.println("Non Static code block----" + A);
        }
    
        StaticClass() {
            this(A);
            A = 3;
            System.out.println("Construction method----" + A);
        }
    
        StaticClass(int i) {
            A = i;
            System.out.println("Construction method with parameters----" + A);
        }
    
        StaticClass(int i, String name) {
            A = i;
            System.out.println("Construction method with parameters----" + A);
        }
    
        public static void main(String[] args) {
            StaticClass sc = new StaticClass();
        }
    }

     反编译之后:

    import java.io.PrintStream;
    
    public class StaticClass { static int A = 5;
      
      static { A = 6;
        System.out.println("Static code block----" + A);
      }
      
      StaticClass()
      {
        this(A);
        A = 3;
        System.out.println("Construction method----" + A);
      }
      
      StaticClass(int paramInt)
      {
        A = 8;
        System.out.println("Non Static code block----" + A);
        
        A = paramInt;
        System.out.println("Construction method with parameters----" + A);
      }
      
      StaticClass(int paramInt, String paramString)
      {
        A = 8;
        System.out.println("Non Static code block----" + A);
        
        A = paramInt;
        System.out.println("Construction method with parameters----" + A);
      }
      
      public static void main(String[] paramArrayOfString) {
        StaticClass localStaticClass = new StaticClass();
      }
    }

      再添加一个三个参数的构造器

    package com.zpj.classload;
    
    /**
     * @author Perkins Zhu
     * @version 2017年1月17日 下午8:07:34
     */
    public class StaticClass {
    
        static int A = 5;
        static {
            A = 6;
            System.out.println("Static code block----" + A);
        }
        {
            A = 8;
            System.out.println("Non Static code block----" + A);
        }
    
        StaticClass() {
            A = 3;
            System.out.println("Construction method----" + A);
        }
    
        StaticClass(int i) {
            A = i;
            System.out.println("Construction method with parameters----" + A);
        }
    
        StaticClass(int i, String name) {
            A = i;
            System.out.println("Construction method with parameters----" + A);
        }
    
        StaticClass(int i, String name, String whatever) {
            A = i;
            System.out.println("Construction method with parameters----" + A);
        }
    
        public static void main(String[] args) {
            StaticClass sc = new StaticClass();
        }
    }

    反编译之后:

    import java.io.PrintStream;
    
    public class StaticClass { static int A = 5;
      
      static { A = 6;
        System.out.println("Static code block----" + A);
      }
      
      StaticClass() {
       A
    = 8; System.out.println("Non Static code block----" + A); A = 3; System.out.println("Construction method----" + A); } StaticClass(int paramInt) { A = 8; System.out.println("Non Static code block----" + A); A = paramInt; System.out.println("Construction method with parameters----" + A); } StaticClass(int paramInt, String paramString) { A = 8; System.out.println("Non Static code block----" + A); A = paramInt; System.out.println("Construction method with parameters----" + A); } StaticClass(int paramInt, String paramString1, String paramString2) { A = 8; System.out.println("Non Static code block----" + A); A = paramInt; System.out.println("Construction method with parameters----" + A); } public static void main(String[] paramArrayOfString) { StaticClass localStaticClass = new StaticClass(); } }

     注意带下划线的地方,如果调用this()其他构造器的构造器便没有添加非静态代码块的代码,没有调用的构造器则每个都有。

     得出结论:

    非静态代码块在进行编译的时候,会自动把非静态代码块中的代码复制到所有没有调用其他构造器的构造器中。

  • 相关阅读:
    MAC LAMP环境 php执行使用问题
    centos 服务器 安全设置
    Linux系统发现占用CPU达100%的进程并处理
    git 使用国内镜像 ,查看镜像更改情况
    mac安装composer
    MySql反向模糊查询
    Linux启动或重启网卡
    MAMP环境 nginx配置忽略index.php入口文件
    php 验证码生成 不保存的情况下 缩小图片质量
    KMP字符串模式匹配详解
  • 原文地址:https://www.cnblogs.com/PerkinsZhu/p/6294552.html
Copyright © 2011-2022 走看看