前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 静态属性与实例属性的初始化

Java 静态属性与实例属性的初始化

作者头像
zhipingChen
发布2019-05-08 10:26:55
2.3K0
发布2019-05-08 10:26:55
举报
文章被收录于专栏:编程理解

类的初始化包括静态属性的初始化和实例属性的初始化,在加载类过程中的准备阶段会给静态属性分配存储空间,并根据属性的类型设置初始值,例如 int 类型静态属性会设置初始值为 0,布尔类型静态属性会设置初始值为 false;实例属性的初始化会在构造实例对象时发生。

这里提到的静态属性不包括静态常量,静态常量会在准备阶段直接赋予指定的初始值。

构造实例对象

代码语言:javascript
复制
public class Test {

    {
        System.out.println("instance initialization");
    }

    static {
        System.out.println("static initialization");
    }

    public static void main(String[] args) {
        new Test();
        new Test();
    }
}

输出结果为:

代码语言:javascript
复制
static initialization
instance initialization
instance initialization

由此可知,静态属性的初始化发生在实例属性的初始化之前,且只发生一次,实例属性在每次创建实例对象会进行初始化。

在加载阶段之后,会在内存中保存一个类的java.lang.Class对象,通过该Class对象来访问类中的各项数据,包括静态属性。所以静态属性只需要初始化赋值一次,生成Class对象后,通过Class对象来访问静态属性,实例属性则会在每次生成实例对象时初始化一次。

加载、验证、准备阶段的顺序只是开始顺序,在某一个时间点,可能同时执行多个阶段的任务。例如加载阶段会将二进制字节流转换为内存中的一个Class对象,获取二进制信息后,会启动验证阶段对字节流进行安全验证,验证通过,准备阶段进行静态属性的内存分配和默认值设置,最后才会生成一个Class对象。

构造子类实例对象

代码语言:javascript
复制
public class Test extends Sup {

    {
        System.out.println("instance initialization");
    }

    static {
        System.out.println("static initialization");
    }

    public static void main(String[] args) {
        new Test();
        new Test();
    }
}

class Sup {
    {
        System.out.println("sup instance initialization");
    }

    static {
        System.out.println("sup static initialization");
    }
}

输出结果为:

代码语言:javascript
复制
sup static initialization
static initialization
sup instance initialization
instance initialization
sup instance initialization
instance initialization

由此可知,在进行子类静态属性初始化时,若父类还没有进行静态初始化,则会先进行父类的静态初始化;在子类实例属性初始化时,若父类还没有进行实例属性初始化,则会先进行父类的实例属性初始化。并且每次构造实例对象都会进行实例属性初始化。

静态属性的定义和使用

代码语言:javascript
复制
public class Test {

    static {
        i = 1;
    }

    private static int i = 2;

    public static void main(String[] args) {
        System.out.println(Test.i);
    }
}

输出结果为:

代码语言:javascript
复制
2

上面提到在准备阶段会对静态属性设置类型默认值,由此可知,示例代码中的静态变量 i,在准备阶段默认值为 0。在初始化阶段,静态代码块和静态变量定义相当于两次赋值,首先设置 i=1,然后 i=2,所以输出值为 2。

通过该示例可知,静态代码块和静态变量定义的赋值操作区分前后顺序,这里有一点需要注意:静态代码中只能访问定义在静态代码块之前的变量,即不能访问未初始化的变量。例如如下情况会编译报错:

代码语言:javascript
复制
public class Test {

    static {
        i = 1;
        System.out.println(i); // 编译不通过 
    }

    private static int i = 2;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.04.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档