构造代码块详解

前面我们已经对代码块做了相应的介绍说说java中的那些代码块 ,这篇我们主要针对构造代码块来做详细介绍。
先看一个简单的例子:

public class ConstructCodeBlock {

    {
        System.out.println("构造代码块1");
    }
    public ConstructCodeBlock(){
        System.out.println("构造方法");
    }
    public ConstructCodeBlock(String name){
        System.out.println("有参构造方法");
    }
    {
        System.out.println("构造代码块2");
    }

    public static void main(String[] args) {
        new ConstructCodeBlock();
        new ConstructCodeBlock("小明");
    }
}
输出结果:
构造代码块1
构造代码块2
构造方法
构造代码块1
构造代码块2
有参构造方法
构造方法与构造代码块

我们知道,一个类中至少有一个构造方法(如果没有,编码器会自动的为其创建一个无参构造方法),构造方法是在对象生产时调用的,从上面的例子我们已经知道,构造代码块是在构造方法前执行的。那么问题来了:构造方法和构造代码块是什么关系呢?构造代码块具体又是什么时候执行呢?
很简单,编译器会把构造代码块插入到每个构造方法的最前端,也就是说上例中的代码等价下面这段代码:

public class ConstructCodeBlock {

    public ConstructCodeBlock(){
        System.out.println("构造代码块1");
        System.out.println("构造代码块2");
        System.out.println("构造方法");
    }
    public ConstructCodeBlock(String name){
        System.out.println("构造代码块1");
        System.out.println("构造代码块2");
        System.out.println("有参构造方法");
    }

    public static void main(String[] args) {
        new ConstructCodeBlock();
        new ConstructCodeBlock("小明");
    }
}

所以说当我们new一个对象时会先执行构造代码块,然后再执行其他代码,也就是说:构造代码块会在每个构造函数内首先执行(注意:构造代码块不是在构造函数之前执行,它是依托于构造函数的执行)。

构造代码块的作用

一个东西存在必须有它作用,不然就没有存在的意义了,而它的作用也是我们最关心的。那构造代码块有什么用呢?
1、初始化实例变量
如果每个构造方法都要初始化变量,可以通过构造代码块来实现。当然也可以通过定义一个方法,然后在每个构造函数中调用该方法来实现,这样也能解决问题,但之前我们就讨论过构造函数尽量简单化(参考构造函数),如果用构造代码块的方式就不用定义和调用了,会直接由编译器写入到每个构造函数中。
2、初始化实例环境
当一个对象必须在适当的场景下才能存在,如果没有适当的场景,就需要在创建此对象时创建此场景。例如,在JEE开发中,要产生HTTP Request必须首先建立HTTP Session,在创建HTTP Request时就可以通构造代码块来检查HTTP Session是否存在,如果不存在就创建HTTP Session对象。
所以很好的利用构造代码块这两个特性不仅可以减少代码量,还可以让程序更容易阅读,特别是当所有的构造函数都要实现逻辑,而且这部分逻辑又很复杂时,就可以通过编写多个构造代码块来实现。每个代码块完成不同业务逻辑,然后按照业务顺序依次存放,这样在创建实例时JVM也就会按照顺序依次执行,实现复杂对象的模块化创建。

来一个真实的案列:统计一个类的访问数量。我们通过构造代码块实现
public class ConstructCodeBlock {

    public static void main(String[] args) {
        new TestCount();
        new TestCount("小明");
        new TestCount(0);
        System.out.println("产生实例对象数量为:"+TestCount.getNumofObjects());
    }

}

class TestCount{
    //对象计数器
    private static int numofObjects = 0;

    {
        //构造代码块,计算产生对象数量
        numofObjects++;
    }

    //无参构造函数
    public TestCount(){

    }

    //有参构造函数调用无参构造函数
    public TestCount(String str){
        this();
    }

    //有参构造函数调用无参构造函数
    public TestCount(int i){

    }

    public static int getNumofObjects(){
        return numofObjects;
    }
}

结果会是多少呢?我们知道编译器会将构造代码块放到构造方法中执行,我们看到在第二个构造函数中使用this()调用了第一个无参构造方法,是不是当我们newTestCount(“小明”)时计数器会执行两次呢?一次执行无参构造函数中的构造代码块,一次执行自身的构造代码块。然而打印的结果是 产生实例对象数量为:3
这是为什么呢,其实并不是每次编译器都会将构造代码块放到构造方法中,有一个特殊情况:如果遇到this关键字(也就是构造方法调用自身其他的构造方法时),编译器将不会在构造代码块放到构造方法中。所以保证了只执行了一次。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值