Java 的构造器和初始化块之间的区别

Java 使用构造器来对单个对象进行初始化操作,使用构造器先完成整个 Java 对象的状态初始化,然后将 Java 对象返回程序,从而让该 Java 对象的信息更加完整。而与构造器作用非常类似的是初始化块,它也可以对 Java 对象进行初始化操作。

1、使用初始化块

一个类里可以有多个初始化块,前面定义的初始化块先执行,后面定义的初始化块后执行。初始化块虽然也是 Java 类的一个成员,但是它没有名字,也就没有标识,因此无法通过类、对象来调用初始化块。初始化块的修饰符只能是 static ,使用 static 修饰的初始化块被称为类初始块(静态初始块)。初始化块里可以包含任意执行语句,包括定义局部变量,调用其他对象的方法,以及使用分支和循环语句。

public class Person
{
    //定义一个初始化块
    {
        int a = 6;
        if( a > 4 )
        {
            System.out.println("Person定义的初始化块:局部定量a的值大于4");
        }
        System.out.println("Person定义的初始化块");
    }
    {
        System.out.println("Person定义的第二个初始化块");
    }
    public Person
    {
        System.out.println("Person类的无参构造函数");
    }
    public static void main(String[] args)
    {
        new Person();
    }
}
//Person定义的初始化块:局部定量a的值大于4
//Person定义的初始化块
//Person定义的第二个初始化块
//Person类的无参构造函数

初始化块只在创建 Java 对象时隐式执行,而且在执行构造器之前执行。

使用 javac 命令编译 Java 类后,该 Java 类中的初始化块会消失,初始化块中代码会被“还原”到每个构造器中,且位于构造器前面

2、关联性

初始化块可以说是构造器的补充,初始化块总是在构造器执行之前执行的。与构造器不同的是,初始化块是一段固定的代码,它不能接收任何参数。因此初始化块对同一个类的所有对象所进行的初始化处理完全相同,利用这一点,我们可以将一段对所有对象完全相同,且无须接收任何参数的初始化处理代码提取到初始化块中,这样能更好地提高初始化代码的复用,提高整个应用的可维护性。
在这里插入图片描述

3、静态初始化块

如果定义初始化块时使用了 static 修饰符,则这个初始化块就变成了静态初始化块,也被称为类初始化块,可以对类进行初始化。静态初始化块是类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象是执行。因此静态初始化块总是比普通初始化块先执行。因为静态初始化块属于类的静态成员,同样需要遵循静态成员不能访问非静态成员的规则,所以不能访问实例变量和实例方法。

下面程序创建三个类:Root、Mid 和 Leaf,这三个类都提供了静态初始化块和普通初始化块,而且 Mid 类里还使用 this 调用重载的构造器,而 Leaf 使用 super 显式调用其父类指定的构造器

class Root
{
    static{
        System.out.println("Root 的静态初始化块");
    }
    {
        System.out.println("Root 的普通初始化块");
    }
    public Root()
    {
        System.out.println("Root 的无参数构造器");
    }
}
class Mid extends Root
{
    static{
        System.out.println("Mid 的静态初始化块");
    }
    {
        System.out.println("Mid 的普通初始化块");
    }
    public Mid()
    {
        System.out.println("Mid 的无参构造器");
    }
    public Mid(String msg)
    {
        this();//通过this调用同一个类中重载的构造器
        System.out.println("Mid 的带参构造器,其参数为" + msg);
    }
}
class Leaf extends Mid
{
    static{
        System.out.println("Leaf 的静态初始化块");
    }
    {
        System.out.println("Leaf 的普通初始化块");
    }
    public Leaf()
    {
        super("和小陈一起学Java");
        System.out.println("执行 Leaf 的构造器");
    }
}
public class Test
{
    public static void main(String[] args)
    {
        new Leaf();
        new Leaf();
    }
}

在这里插入图片描述
第一次创建一个 Leaf 对象时,因为系统中还不存在 Leaf 类,因此需要先加载并初始化 Leaf 类,初始化 Leaf 类时会先执行其顶层父类的静态初始化块,再执行其直接父类的静态初始化块,最后才执行 Leaf 本身的静态初始化块。一旦 Leaf 类初始化成功后,Leaf 类就在该虚拟机里将一直存在,因此第二次创建 Leaf 实例时无须再次对 Leaf 类进行初始化。

静态初始化块在以后编写 C3P0 数据连接池的工具类时会被运用到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值