专栏首页编程理解Java 静态属性与实例属性的初始化

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

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

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

构造实例对象

public class Test {

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

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

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

输出结果为:

static initialization
instance initialization
instance initialization

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

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

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

构造子类实例对象

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

输出结果为:

sup static initialization
static initialization
sup instance initialization
instance initialization
sup instance initialization
instance initialization

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

静态属性的定义和使用

public class Test {

    static {
        i = 1;
    }

    private static int i = 2;

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

输出结果为:

2

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

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

public class Test {

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

    private static int i = 2;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 数据结构(九):广度优先与深度优先

    广度优先搜索(breadth-first search)和深度优先搜索(depth-first search)是两种探索图/树中顶点的思路。这两种搜索方式可以用...

    zhipingChen
  • Leetcode 189. 旋转数组

    输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右旋转 1 步: [7,1,2,3,4,5,6]...

    zhipingChen
  • 数据结构(十三):最短路径(Floyd算法)

    Floyd-Warshall 算法使用动态规划策略计算图中每两个顶点间的最短路径,算法中通过调整路径中经过的中间顶点来缩小路径权值,最终得到每对顶点间的最短路径...

    zhipingChen
  • 神经网络到底该如何初始化?吴恩达Deeplearning.ai最新干货

    初始化会对深度神经网络模型的训练时间和收敛性产生重大影响。简单的初始化方法可以加速训练,但使用这些方法需要注意小心常见的陷阱。本文将解释如何有效地对神经网络参数...

    abs_zero
  • 一文读懂神经网络初始化!吴恩达Deeplearning.ai最新干货

    初始化会对深度神经网络模型的训练时间和收敛性产生重大影响。简单的初始化方法可以加速训练,但使用这些方法需要注意小心常见的陷阱。本文将解释如何有效地对神经网络参数...

    数据派THU
  • 一文看懂神经网络初始化!吴恩达Deeplearning.ai最新干货

    初始化会对深度神经网络模型的训练时间和收敛性产生重大影响。简单的初始化方法可以加速训练,但使用这些方法需要注意小心常见的陷阱。本文将解释如何有效地对神经网络参数...

    磐创AI
  • 虚拟机的类加载机制1 类加载的时机

    JavaEdge
  • Java编程思想学习录(连载之:初始化与清理)

    CodeSheep
  • 为何Keras中的CNN是有问题的,如何修复它们?

    上个星期我做了一些实验,用了在 CIFAR10 数据集上训练的 VGG16。我需要从零开始训练模型,所以没有使用在 ImageNet 上预训练的版本。

    磐创AI
  • 一文看懂神经网络初始化!吴恩达Deeplearning.ai最新干货

    初始化会对深度神经网络模型的训练时间和收敛性产生重大影响。简单的初始化方法可以加速训练,但使用这些方法需要注意小心常见的陷阱。本文将解释如何有效地对神经网络参数...

    新智元

扫码关注云+社区

领取腾讯云代金券