资讯专栏INFORMATION COLUMN

java基础-静态,非静态(构造)代码块,类加载

vvpale / 2056人阅读

摘要:想来想去先来一题比较好输出结果分析类初始化顺序父类静态变量父类静态代码块子类静态代码块父类非静态变量父类非静态代码块父类构造函数子类非静态变量子类非静态代码块子类构造函数非静态代码块输出结果顺序非静态代码块被编译器拷贝到了构造块内所以称

static block and non-static block(constructor block)

[toc]

想来想去,先来一题比较好
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

分析

Invoking Baz.testAsserts() cause Baz to be initialized

default value int x=0;

Before Baz initialize , Bar must be initialized

Bar"s static initializer again invoking Baz.testAsserts()

so x is 0 , then x+2 , x=2

go on initializing Baz , init x = 1;

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");
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68402.html

相关文章

  • JAVA快速复习

    摘要:八种基本数据类型数组定义数组元素类型数组名元素类型元素个数和数组长度元素类型数组名元素类型元素元素元素元素内存的划分寄存器本地方法区方法区栈内存存储局部变量变量所属作用域一旦结束变量自动释放方法进栈局部变量属于方法所以方法要先进栈堆内存存储 八种基本数据类型 byte short int long boolean char float double JAVA数组 定义数组 元...

    cppowboy 评论0 收藏0
  • Java初始化顺序

    摘要:对子类成员数据按照它们声明的顺序初始化,执行子类构造函数的其余部分。参考类的初始化顺序引了大半类加载的时机 jvm系列 垃圾回收基础 JVM的编译策略 GC的三大基础算法 GC的三大高级算法 GC策略的评价指标 JVM信息查看 GC通用日志解读 jvm的card table数据结构 Java类初始化顺序 Java对象结构及大小计算 Java的类加载机制 Java对象分配简要流程 年老...

    boredream 评论0 收藏0
  • 一道面试题引发的思考:(1)

    这是网易2015校招Java面试题,直接上题目。 题目 package com.mousycoder.staticTest; public class HelloB extends HelloA { public HelloB() { System.out.println(HelloB); } { System.out.println(I...

    tommego 评论0 收藏0
  • java基础小记

    摘要:看到的只是,而由泛型附加的类型信息对来说是不可见的。然后再加载执行类的静态变量以及静态语句块。接口中基本数据类型为而抽类象不是的。本地方法接口主要是调用或实现的本地方法及返回结果。用户自定义类加载器,在程序运行期间,通过的子类动态加载。 编译机制  编译主要是把 .Java文件转换为 .class 文件。其中转换后的 .class 文件就包含了元数据,方法信息等一些信息。比如说元数据就...

    ruicbAndroid 评论0 收藏0
  • Java代码执行顺序

    摘要:没有关键字修饰的如实例变量非静态变量非静态代码块初始化实际上是会被提取到类的构造器中被执行的,但是会比类构造器中的代码块优先执行到,非静态实例变量非静态代码块的地位是相等的,它们将按顺序被执行。 阅读原文:Java代码执行顺序 程序中代码执行的顺序非常重要,稍有不慎便会是程序运行出错,那么我将结合实例来分析代码中的执行。 名词解释 首先了解几个名词: 非静态代码块 直接由 { } 包起...

    hosition 评论0 收藏0

发表评论

0条评论

vvpale

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<