代码块的那点事

谈到代码块,大家可能会不屑一顾,但是你真正懂它们吗?可以从下面几点检验:
- 代码块的定义及分类
- 代码块的作用
- 代码块的执行顺序

代码块的那些琐事

  1. 代码块的定义及共性
    • 简言之,用 {} 包起来的代码片段,就可以称之为代码块;
    • 不同类型的代码块之间的执行顺序与其代码的相对位置无关;
    • 同一种类型的代码块在代码中由上而下顺序执行;
  2. 代码块的分类
    • 局部代码块
      定义:处于处于方法中的局部位置;
      作用:限定变量、对象的生命周期,迟创建、早释放,提高内存利用率;
    • 构造代码块
      定义:处于类中的成员位置,用{}括起来的代码片段。
      说明:每创建一个对象,就会调用构造代码块一次。且在调用构造方法之前、静态方法之后调用;
      作用:抽取出对象共同的初始化属性代码。
    • 静态代码块
      定义:与构造代码块类似,不过其用 static 来修饰;
      说明:在类加载的过程中被调用,且只加载一次、最先被调用。同一个类中静态代码块会先于 main 函数执行;
      作用:对类的数据进行初始化,仅只执行一次。

一个实例搞定代码块家族的调用顺序

package com.george.j2se.codeblock;

/***
 * @author george
 * @email qtozeng@qq.com
 * @date 2016-4-3
 */
class Student {

    static {
        System.out.println("我是 Student 静态代码块");
    }

    {
        System.out.println("我是 Student 构造代码块");
    }

    public Student() {
        System.out.println("我是 Student 无参构造方法");
    }

}

public class StudentTest {
    static {
        System.out.println("我是 main 函数所处类的静态代码块,我最先执行!");
    }

    public static void main(String[] args) {
        System.out.println("我是 main方法");

        Student s1 = new Student();
        Student s2 = new Student();

    }

}

执行输出:

我是 main 函数所处类的静态代码块,我最先执行!
我是 main方法
我是 Student 静态代码块
我是 Student 构造代码块
我是 Student 无参构造方法
我是 Student 构造代码块
我是 Student 无参构造方法

网友提供的一段代码

package com.george.j2se;

/***
 * @author george
 * @email  qtozeng@qq.com
 * @date   2016-4-3
 */
public class TestStaticCon {
    public static int a = 0;

    static {
        a = 10;
        System.out.println("静态代码块在执行 a=" + a);
    }

    {
        a = 8;
        System.out.println("构造代码块在执行 a=" + a);
    }

    public TestStaticCon() {
        this("带参构造方法中被无参构造调用 a=" + a); // 调用另外一个构造方法
        System.out.println("无参构造方法执行 a=" + a);
    }

    public TestStaticCon(String n) {
        System.out.println(n);
        System.out.println("带参构造方法中执行 a=" + a);

    }

    public static void main(String[] args) {
        TestStaticCon tsc = null;
        System.out.println("main 方法要创建对象了...");
        tsc = new TestStaticCon();
    }
}

执行输出:

静态代码块在执行 a=10
main 方法要创建对象了...
构造代码块在执行 a=8
带参构造方法中被无参构造调用 a=10
带参构造方法中执行 a=8
无参构造方法执行 a
  1. 问题来了:
    有同学可能会疑问,为什么在带无参构造中调用带参构造方法时,a 的值为 10,不应该是 8 吗?那是因为没有理解构造代码块执行时机的本质,其是在创建对象前被调用,而不是在调用构造方法前被调用
  2. 思维误区:
    构造方法被调用与创建对象是不等价的。显然,一个构造方法可以调用其它构造方法,然而,在此过程中,可能就只创建了一个对象。构造方法除了会被 jvm 自动调用外,其与普通方法无根本区别,只是一般用作给对象初始化而已。、
  3. 那么结论:
    所以更为准确的说,构造代码块是在创建对象前被调用的,也可以说,是在调用最后一个构造方法前被调用的。(若仍有疑惑可以实验以下实例)
  4. 反观字节码:
    部分反编译后的字节码文件

一个补充的实例

package com.george.j2se.codeblock;

/***
 * @author george
 * @email  qtozeng@qq.com
 * @date   2016-4-3
 */
public class PersonTest {

    private int id;
    private String name;

    {
        System.out.println("构造代码块被调用了!");
    }

    public PersonTest() {
        this(100);
        System.out.println("public PersonTest() 被调用...");
    }

    public PersonTest(int id) {
        this(id, "tom");
        this.id = id;
        System.out.println("public PersonTest(int id) 被调用..." );
    }


    public PersonTest(int id, String name) {
        this.id = id;
        this.name = name;
        System.out.println("public PersonTest(int id, String name) 被调用...");
    }

    public static void main(String[] args) {
        PersonTest pt = new PersonTest();
    }
}

执行输出:

构造代码块被调用了!
public PersonTest(int id, String name) 被调用...
public PersonTest(int id) 被调用...
public PersonTest() 被调用...

同学不妨用断点调试一下代码,结果就一目了然了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值