zoukankan      html  css  js  c++  java
  • java基础-静态,非静态(构造)代码块,类加载

    static block and non-static block(constructor block)

    想来想去,先来一题比较好

    public class Foo {
        public static void main(String[] args) {
            Baz.testAsserts();
            Baz.testAsserts();
            // Will execute after Baz is initialized.
        }
    }
    
    class Bar {
        static {
            Baz.testAsserts();
            // Will execute before Baz is initialized!
        }
    }
    
    
    class Baz extends Bar {
        static int x = 1;
    
        static void testAsserts() {
    
            System.out.println("x is " + x);
            x=x+2;
        }
    
    }
    
    • 输出结果

    x is 0
    x is 1
    x is 3

    • 分析
    1. Invoking Baz.testAsserts() cause Baz to be initialized
    2. default value int x=0;
    3. Before Baz initialize , Bar must be initialized
    4. Bar's static initializer again invoking Baz.testAsserts()
    5. so x is 0 , then x+2 , x=2
    6. go on initializing Baz , init x = 1;
    7. Invoking Baz.testAsserts() x = 1 , so x is 1;

    Java类初始化顺序

    父类静态变量 ——>父类静态代码块——>子类静态代码块——>父类非静态变量 ——>
    父类非静态代码块——>父类构造函数 ——>子类非静态变量——>子类非静态代码块——>
    子类构造函数

    非静态代码块 non-static block(constructor block)

    class A {
    
        int x ;
    
        //block num 1
        {
            x = 1;
            System.out.println("block num 1, x is " + x);
        }
    
        A() {
            x = 3;
            System.out.println("constructor block x is " + x);
        }
    
        //block num 2
        {
            x = 2;
            System.out.println("block num 2, x is " + x);
        }
    
    }
    
    
    public class Non_staticBlock {
    
        public static void main(String[] args) {
    
            String newLine = System.getProperty("line.separator");
    
            System.out.println("====first time instantiate ====" + newLine);
            new A();
    
            System.out.println(" 
    ====second time instantiate ====" + newLine);
            new A();
        }
    
    }
    
    • 输出结果、顺序

    ====first time instantiate ====

    block num 1, x is 1
    block num 2, x is 2
    constructor x is 3

    ====second time instantiate ====

    block num 1, x is 1
    block num 2, x is 2
    constructor x is 3

    • 非静态代码块被java编译器拷贝到了构造块内,所以称为"constructor block"也是可以的,所以每次 new 构造函数也都执行
    • .class 文件如下, 非静态代码块被java编译器拷贝到了构造块内.
    class A {
        int x = 1;
    
        A() {
            System.out.println("block num 1, x is " + this.x);
            this.x = 2;
            System.out.println("block num 2, x is " + this.x);
            this.x = 3;
            System.out.println("constructor x is " + this.x);
        }
    }
    
    

    静态代码块 static block

    class AA {
    
        AA() {
            x = 3;
            System.out.println("constructor x is " + x);
        }
    
        static int x = 1;
    
        //block num 1
        static {
            System.out.println("static block num 1 , x is " + x);
        }
    
        //block num 2
        static {
            x = 2;
            System.out.println("static block num 2 , x is " + x);
        }
    
        static void print() {
            System.out.println("static method");
        }
    }
    
    
    public class StaticBlock {
            static {
            System.out.println("==== first ====");
        }
    
        public static void main(String[] args) {
            String newLine = System.getProperty("line.separator");
            System.out.println("====AA class init ====" + newLine);
            // class init
            AA.print();
            
            System.out.println(" 
    ====fisrt time instantiate AA====" + newLine);
            
            new AA();
            System.out.println(" 
    ====sencond time instantiate AA====" + newLine);
            new AA();
        }
    }
    
    • 输出结果、顺序

    ==== first ====
    ====AA class init ====

    static block num 1 , x is 1
    static block num 2 , x is 2
    static method
    ==== first time instantiate AA ====

    constructor x is 3

    ==== second time instantiate AA ====

    constructor x is 3

    • 由于JVM在加载类时会执行静态代码块,且只会执行一次. 本例静态引用AA.print(); 触发类初始化
    • 静态代码块先于主方法执行,本例优先打印first
    • 更多内容搜索jvm类加载
    • .class 文件如下
    class AA {
        static int x = 1;
    
        AA() {
            x = 3;
            System.out.println("constructor x is " + x);
        }
    
        static void print() {
            System.out.println("static method");
        }
    
        static {
            System.out.println("static block num 1 , x is " + x);
            x = 2;
            System.out.println("static block num 2 , x is " + x);
        }
    }
    

    联合看一下

    class AAA {
        int x;
    
        //block num 1
        {
            x = 1;
            System.out.println("non-static block num 1 x is " + x);
        }
    
        AAA() {
            x = 3;
            System.out.println("constructor x is " + x);
    
        }
    
        //block num 2
        {
            x = 2;
            System.out.println("non-static block num 2 x is " + x);
        }
    
    
        // The static block only gets called once,when the class itself is initialized,
        // no matter how many objects of that type you create
        static {
            System.out.println("static block");
        }
    
    
        //Gets called every time an instance of the  class is constructed.
        //the non-static block is actually copied by the Java compiler into every constructor the class has (source).
        //So it is still the constructor's job to initialize fields.
        //to understand "actually " , find the result in the .class file of A.class
        {
            System.out.println("non-static block");
        }
    }
    
    
    public class BlockSample {
    
        public static void main(String[] args) {
    
            String newLine = System.getProperty("line.separator");
    
            System.out.println("====first time instantiate AAA ====" + newLine);
            new AAA();
    
            System.out.println(" 
    ====second time instantiate AAA ====" + newLine);
            new AAA();
    
        }
    }
    
    • 输出结果、顺序

    ====first time instantiate AAA ====

    static block
    non-static block num 1 x is 1
    non-static block num 2 x is 2
    non-static block
    constructor x is 3

    ====second time instantiate AAA ====

    non-static block num 1 x is 1
    non-static block num 2 x is 2
    non-static block
    constructor x is 3

    • .class 文件
    class AAA {
        int x = 1;
    
        AAA() {
            System.out.println("non-static block num 1 x is " + this.x);
            this.x = 2;
            System.out.println("non-static block num 2 x is " + this.x);
            System.out.println("non-static block");
            this.x = 3;
            System.out.println("constructor x is " + this.x);
        }
    
        static {
            System.out.println("static block");
        }
    }
    
  • 相关阅读:
    vim插件:显示树形目录插件NERDTree安装 和 使用【转】
    CMake 入门实战【转】
    在 linux 下使用 CMake 构建应用程序【转】
    Buildroot构建指南——根文件系统(Rootfs)【转】
    Buildroot构建指南--快速上手与实用技巧【转】
    Vim升华之树形目录插件NERDTree安装图解【转】
    【转】Android端与Android端利用WIFI进行FTP通信
    【转】Android 服务器之SFTP服务器上传下载功能 -- 不错
    【转】session setup failed: NT_STATUS_LOGON_FAILURE -- 不错
    【转】Mac OS X开机启动Path had bad permissions错误解决方案
  • 原文地址:https://www.cnblogs.com/dayou123123/p/8404741.html
Copyright © 2011-2022 走看看