Java父类与子类中静态代码块 实例代码块 静态变量 实例变量 构造函数执行顺序

本文深入解析Java中类加载过程中静态代码块、实例代码块、静态变量及实例变量的执行顺序,通过具体示例代码和反编译结果进行验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实例化子类时,父类与子类中的静态代码块、实例代码块、静态变量、实例变量、构造函数的执行顺序是怎样的?


代码执行的优先级为:

firest:静态部分

second:实例化过程


详细顺序为:

1.父类静态代码块与父类静态变量赋值(取决于代码书写顺序)

2.子类静态代码块与子类静态变量赋值(取决于代码书写顺序)

3.父类实例变量赋值与父类代码块(取决于代码书写顺序)

4.父类构造函数

5.子类实例变量赋值与子类代码块(取决于代码书写顺序)

6.子类构造函数


在JVM加载完类以后,类在被使用的时候初始化,静态部分只在类初始化的时候执行一次。


测试代码:


class Father {

    Father() {
        LogUtil.log(System.currentTimeMillis() + " ------ 父类构造函数");
    }

    static {
        LogUtil.log(System.currentTimeMillis() + " ------ 父类静态代码块");
    }

    long x = getTime(" ------ 父类实例变量赋值");

    {
        long time = System.currentTimeMillis();
        LogUtil.log(time + " ------ 父类代码块");
    }

    static long y = getTime(" ------ 父类静态变量赋值");

    static long getTime(String who) {
        long time = System.currentTimeMillis();
        LogUtil.log(time + who);
        return time;
    }
}

class Child extends Father {

    Child() {
        LogUtil.log(System.currentTimeMillis() + " ------ 子类构造函数");
    }

    static long y = getTime(" ------ 子类静态变量赋值");

    static {
        LogUtil.log(System.currentTimeMillis() + " ------ 子类静态代码块");
    }

    {
        long time = System.currentTimeMillis();
        LogUtil.log(time + " ------ 子类代码块");
    }

    long x = getTime(" ------ 子类实例变量赋值");

    static long getTime(String who) {
        long time = System.currentTimeMillis();
        LogUtil.log(time + who);
        return time;
    }
}

调用代码:

new Thread(new Runnable() {
            @Override
            public void run() {
                new Child();
                LogUtil.log("分隔符 ------ 分隔符");
                new Child();
            }
        }).start();

执行结果:

11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 父类静态代码块
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 父类静态变量赋值
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 子类静态变量赋值
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 子类静态代码块
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 父类实例变量赋值
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 父类代码块
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 父类构造函数
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 子类代码块
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 子类实例变量赋值
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 子类构造函数
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 分隔符 ------ 分隔符
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 父类实例变量赋值
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 父类代码块
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523353 ------ 父类构造函数
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523354 ------ 子类代码块
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523354 ------ 子类实例变量赋值
11-03 20:02:03.350 7533-7881/? E/AKADDEMO: 1478174523354 ------ 子类构造函数

-------------2018.1.5---------------

我们通过反编译工具(IntelliJ IDEA或JD-JUI)反编译一下class文件看能发现什么有意思的东西

测试代码:

class Father {

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    private static long a = getTime(" -----a 父类静态变量赋值" + '\n');
    private final static long b = getTime(" -----b 父类静态变量赋值" + '\n');

    static {
        System.out.print(System.currentTimeMillis() + " ------ 父类静态代码块" + '\n');
    }

    long aa = getTime(" ----aa 父类实例变量赋值" + '\n');

    {
        System.out.print(System.currentTimeMillis() + " ------ 父类代码块" + '\n');
    }

    long bb = getTime(" ----bb 父类实例变量赋值" + '\n');

    static long z = getTime(" -----z 父类静态变量赋值" + '\n');

    static long getTime(String who) {
        long time = System.currentTimeMillis();
        System.out.print(time + who);
        return time;
    }

    private static long c = getTime(" -----c 父类静态变量赋值" + '\n');
    private final static long d = getTime(" -----d 父类静态变量赋值" + '\n');
}
调用代码:

public static void main(String[] args) {
        new Father();
    }
执行结果:

1515134833612 -----a 父类静态变量赋值
1515134833614 -----b 父类静态变量赋值
1515134833614 ------ 父类静态代码块
1515134833614 -----z 父类静态变量赋值
1515134833614 -----c 父类静态变量赋值
1515134833614 -----d 父类静态变量赋值
1515134833614 ----aa 父类实例变量赋值
1515134833614 ------ 父类代码块
1515134833614 ----bb 父类实例变量赋值
1515134833614 ------ 父类构造函数
用 IntelliJ IDEA 打开上述代码编译之后的 Father.class :

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.ak.torch.videoplayer.disassamble;

public class Father {
    private static long a = getTime(" -----a 父类静态变量赋值\n");
    private static final long b = getTime(" -----b 父类静态变量赋值\n");
    long aa = getTime(" ----aa 父类实例变量赋值\n");
    long bb;
    static long z;
    private static long c;
    private static final long d;

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类代码块" + '\n');
        this.bb = getTime(" ----bb 父类实例变量赋值\n");
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    static long getTime(String var0) {
        long var1 = System.currentTimeMillis();
        System.out.print(var1 + var0);
        return var1;
    }

    static {
        System.out.print(System.currentTimeMillis() + " ------ 父类静态代码块" + '\n');
        z = getTime(" -----z 父类静态变量赋值\n");
        c = getTime(" -----c 父类静态变量赋值\n");
        d = getTime(" -----d 父类静态变量赋值\n");
    }
}
可以发现:

1、在 Father.java 中静态变量a、b的赋值操作写在了静态代码块的前面,静态变量z、c、d的赋值操作写在了静态代码块的后面,查看反编译之后的代码,可见静态变量z、c、d的赋值被写在了静态代码块中。

2、在 Father.java 中实例变量aa的赋值操作写在了实例代码块的前面,实例变量bb的赋值操作写在了实例代码块的后面,查看反编译之后的代码,可见代码块中的操作实例变量b的赋值都被写在了构造函数中。


下面分情况删除一些代码,我们看一下反编译之后的不同

情况一:删掉静态代码块,此时的 Father.java 代码:

class Father {

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    private static long a = getTime(" -----a 父类静态变量赋值" + '\n');
    private final static long b = getTime(" -----b 父类静态变量赋值" + '\n');

    long aa = getTime(" ----aa 父类实例变量赋值" + '\n');

    {
        System.out.print(System.currentTimeMillis() + " ------ 父类代码块" + '\n');
    }

    long bb = getTime(" ----bb 父类实例变量赋值" + '\n');

    static long z = getTime(" -----z 父类静态变量赋值" + '\n');

    static long getTime(String who) {
        long time = System.currentTimeMillis();
        System.out.print(time + who);
        return time;
    }

    private static long c = getTime(" -----c 父类静态变量赋值" + '\n');
    private final static long d = getTime(" -----d 父类静态变量赋值" + '\n');
}
用 IntelliJ IDEA 打开上述代码编译之后的 Father.class :

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.ak.torch.videoplayer.disassamble;

public class Father {
    private static long a = getTime(" -----a 父类静态变量赋值\n");
    private static final long b = getTime(" -----b 父类静态变量赋值\n");
    long aa = getTime(" ----aa 父类实例变量赋值\n");
    long bb;
    static long z = getTime(" -----z 父类静态变量赋值\n");
    private static long c = getTime(" -----c 父类静态变量赋值\n");
    private static final long d = getTime(" -----d 父类静态变量赋值\n");

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类代码块" + '\n');
        this.bb = getTime(" ----bb 父类实例变量赋值\n");
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    static long getTime(String var0) {
        long var1 = System.currentTimeMillis();
        System.out.print(var1 + var0);
        return var1;
    }
}
可以发现:

任何一个静态变量的赋值都没有被写在静态代码块中


情况二:删掉实例代码块,此时的 Father.java 代码:

class Father {

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    private static long a = getTime(" -----a 父类静态变量赋值" + '\n');
    private final static long b = getTime(" -----b 父类静态变量赋值" + '\n');

    static {
        System.out.print(System.currentTimeMillis() + " ------ 父类静态代码块" + '\n');
    }

    long aa = getTime(" ----aa 父类实例变量赋值" + '\n');

    long bb = getTime(" ----bb 父类实例变量赋值" + '\n');

    static long z = getTime(" -----z 父类静态变量赋值" + '\n');

    static long getTime(String who) {
        long time = System.currentTimeMillis();
        System.out.print(time + who);
        return time;
    }

    private static long c = getTime(" -----c 父类静态变量赋值" + '\n');
    private final static long d = getTime(" -----d 父类静态变量赋值" + '\n');
}
用 IntelliJ IDEA 打开上述代码编译之后的 Father.class :

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.ak.torch.videoplayer.disassamble;

public class Father {
    private static long a = getTime(" -----a 父类静态变量赋值\n");
    private static final long b = getTime(" -----b 父类静态变量赋值\n");
    long aa = getTime(" ----aa 父类实例变量赋值\n");
    long bb = getTime(" ----bb 父类实例变量赋值\n");
    static long z;
    private static long c;
    private static final long d;

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    static long getTime(String var0) {
        long var1 = System.currentTimeMillis();
        System.out.print(var1 + var0);
        return var1;
    }

    static {
        System.out.print(System.currentTimeMillis() + " ------ 父类静态代码块" + '\n');
        z = getTime(" -----z 父类静态变量赋值\n");
        c = getTime(" -----c 父类静态变量赋值\n");
        d = getTime(" -----d 父类静态变量赋值\n");
    }
}

可以发现:

任何一个实例变量的赋值都没有被写在构造函数中


情况三:删掉静态变量,此时的 Father.java 代码:

class Father {

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    static {
        System.out.print(System.currentTimeMillis() + " ------ 父类静态代码块" + '\n');
    }

    long aa = getTime(" ----aa 父类实例变量赋值" + '\n');

    {
        System.out.print(System.currentTimeMillis() + " ------ 父类代码块" + '\n');
    }

    long bb = getTime(" ----bb 父类实例变量赋值" + '\n');

    static long getTime(String who) {
        long time = System.currentTimeMillis();
        System.out.print(time + who);
        return time;
    }
}
用 IntelliJ IDEA 打开上述代码编译之后的 Father.class :

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.ak.torch.videoplayer.disassamble;

public class Father {
    long aa = getTime(" ----aa 父类实例变量赋值\n");
    long bb;

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类代码块" + '\n');
        this.bb = getTime(" ----bb 父类实例变量赋值\n");
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    static long getTime(String var0) {
        long var1 = System.currentTimeMillis();
        System.out.print(var1 + var0);
        return var1;
    }

    static {
        System.out.print(System.currentTimeMillis() + " ------ 父类静态代码块" + '\n');
    }
}


情况四:删掉实例变量,此时的 Father.java 代码:

class Father {

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    private static long a = getTime(" -----a 父类静态变量赋值" + '\n');
    private final static long b = getTime(" -----b 父类静态变量赋值" + '\n');

    static {
        System.out.print(System.currentTimeMillis() + " ------ 父类静态代码块" + '\n');
    }

    {
        System.out.print(System.currentTimeMillis() + " ------ 父类代码块" + '\n');
    }

    static long z = getTime(" -----z 父类静态变量赋值" + '\n');

    static long getTime(String who) {
        long time = System.currentTimeMillis();
        System.out.print(time + who);
        return time;
    }

    private static long c = getTime(" -----c 父类静态变量赋值" + '\n');
    private final static long d = getTime(" -----d 父类静态变量赋值" + '\n');
}

用 IntelliJ IDEA 打开上述代码编译之后的 Father.class :

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.ak.torch.videoplayer.disassamble;

public class Father {
    private static long a = getTime(" -----a 父类静态变量赋值\n");
    private static final long b = getTime(" -----b 父类静态变量赋值\n");
    static long z;
    private static long c;
    private static final long d;

    Father() {
        System.out.print(System.currentTimeMillis() + " ------ 父类代码块" + '\n');
        System.out.print(System.currentTimeMillis() + " ------ 父类构造函数" + '\n');
    }

    static long getTime(String var0) {
        long var1 = System.currentTimeMillis();
        System.out.print(var1 + var0);
        return var1;
    }

    static {
        System.out.print(System.currentTimeMillis() + " ------ 父类静态代码块" + '\n');
        z = getTime(" -----z 父类静态变量赋值\n");
        c = getTime(" -----c 父类静态变量赋值\n");
        d = getTime(" -----d 父类静态变量赋值\n");
    }
}

总结一下:


一、静态代码块 与 静态变量赋值 在反编译成的代码中的位置

1、如果存在静态代码块,并且有静态变量的赋值写在了静态代码块的下面,那么这样的静态变量最终的赋值操作会被写在静态代码块中

2、如果存在多个静态代码块,最终会合并为一个

二、实例变量赋值 与 实例代码块 在反编译成的代码中的位置

1、如果存在实例代码块,并且有实例变量的赋值写在了实例代码块的下面,那么实例代码块中的操作这样的实例变量最终的赋值操作会被写在构造函数中

2、实例代码块中的操作都会被写在构造函数中

3、如果存在多个实例代码块,都会被写在构造函数中


了解了变量赋值与代码块的执行顺序,就能从代码执行的角度解释有时候在代码块中使用变量时为什么会提示“非法前向引用(illegal forward reference)”


反编译工具 IntelliJ IDEA 的BUG

根据 静态代码块 与 静态变量赋值 的执行顺序取决于代码书写顺序这一原则,测试Father.java

class Father {

    static {
        bb = getTime(" ----bb 父类实例变量" + '\n');
    }

    static long aa = getTime(" ----aa 父类实例变量" + '\n');
    static long bb;

    static long getTime(String who) {
        long time = System.currentTimeMillis();
        System.out.print(time + who);
        return time;
    }
}
执行结果:

1515149709262 ----bb 父类实例变量
1515149709262 ----aa 父类实例变量
用 IntelliJ IDEA 打开上述代码编译之后的 Father.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.ak.torch.videoplayer.disassamble;

public class Father {
    static long aa = getTime(" ----aa 父类实例变量\n");
    static long bb = getTime(" ----bb 父类实例变量\n");

    public Father() {
    }

    static long getTime(String var0) {
        long var1 = System.currentTimeMillis();
        System.out.print(var1 + var0);
        return var1;
    }
}
将此反编译之后的代码重新搞一个java文件,然后编译运行:

1515151279918 ----aa 父类实例变量
1515151279919 ----bb 父类实例变量

可见由IntelliJ IDEA反编译出的代码的执行顺序已经不是原来类该有的顺序了,IntelliJ IDEA反编译处理的 实例代码块 与 实例变量的执行顺序也有类似问题。

经过测试,用 JD-JUI 反编译也会有上述的问题,但是兼容性比 IntelliJ IDEA 好一些。

所以,这两款反编译工具反编译出来的代码并不能保证跟原来类的逻辑完全一致。

使用javap命令可以获取类初始化时代码的正确执行顺序。

<think>首先,用户的问题是关于Java子类实例化时父类构造器方法的执行顺序。具体来说,用户问:"Java 子类实例化时 父类构造方法执行顺序 方法调用顺序"。我需要基于系统指令提供的引用来回答。 系统指令要求: - 所有行内数学表达式用$...$格式(但这个问题可能不涉及数学表达式)。 - 独立公式用$$...$$格式(同样,可能不适用)。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 用户提供的引用包括: - [^1]: 子类调用父类构造方法,Java虚拟机先执行父类构造方法,再执行子类构造方法。 - [^2]: 执行顺序父类静态代码块 -> 子类静态代码块 -> 父类构造代码块 -> 父类构造方法 -> 子类构造代码块 -> 子类构造方法。 - [^3]: 子类初始化时调用父类构造方法,通常有隐式的super()调用父类无参数构造方法。 - [^4]: 详细示例显示执行顺序,包括构造函数、属性、方法的初始化。 用户的上一个问题似乎是关于子类实例化时的顺序,所以我需要综合这些引用来构建回答。 回答结构: 1. **逐步解释执行顺序**:基于引用[^2][^4],列出完整的执行顺序。 2. **关键点**: - 父类构造方法先执行。 - 静态代码块优先于实例初始化。 - 构造代码块在构造方法之前。 - 方法调用顺序取决于实例类型。 3. **使用示例**:提供一个简单的代码示例来演示顺序。 4. **生成相关问题**:在结尾添加相关问题,如指令要求。 完整执行顺序(基于引用[^2]): - 父类静态代码块 - 子类静态代码块 - 父类构造代码块 - 父类构造方法 - 子类构造代码块 - 子类构造方法 在方法调用中,如果子类覆盖了方法,调用时会使用子类的方法版本(多态)。 回答应清晰、结构化: - 引言:简述顺序。 - 详细步骤:分步解释。 - 示例:提供代码输出。 - 总结:强调关键点。 - 相关问题:添加相关问题。 相关问题生成(基于指令示例): 1. Java静态代码块实例初始化块的区别? 2. 如何显式调用父类构造方法? 3. 多态在方法调用中如何工作? 4. 如果父类没有无参数构造方法,子类如何处理? 确保引用自然添加:在解释中,当提到特定点时,添加引用标识,如[^2]。 最终回答用中文。</think>### Java子类实例化时父类构造方法方法的执行顺序Java中,当创建子类实例时,父类子类的构造方法、初始化块(包括静态实例块)以及方法调用遵循特定的顺序。这个顺序Java的类加载初始化机制决定,确保对象从父类继承的成员被正确初始化。下面我将逐步解释这个顺序,并提供一个代码示例来演示。整个过程基于Java的类加载初始化规则,确保可靠性准确性。 #### 关键执行顺序总结 当实例子类时,完整的执行顺序如下(从类加载到对象初始化): 1. **静态初始化**:优先执行父类静态代码块,然后执行子类静态代码块(只在类首次加载时执行一次)。 2. **父类实例初始化**:执行父类实例初始化块(构造代码块),然后执行父类的构造方法。 3. **子类实例初始化**:执行子类实例初始化块(构造代码块),然后执行子类的构造方法。 4. **方法调用**:如果子类覆盖了父类的方法,在调用时会基于对象的实际类型(子类执行多态行为。 完整的顺序链为: 父类静态代码块子类静态代码块父类构造代码块父类构造方法 → 子类构造代码块子类构造方法[^2]。 #### 详细步骤解释 1. **静态初始化阶段(类加载时)**: - Java虚拟机(JVM)加载类时,先加载父类执行静态代码块(`static { ... }`)。 - 然后加载子类执行静态代码块静态代码块执行一次,无论创建多少实例。 2. **父类实例初始化阶段**: - 当通过`new SubClass()`创建子类对象时,JVM首先隐式调用父类的构造方法(通常通过`super()`,默认调用父类无参构造方法)。 - 在父类构造方法执行前,先执行父类实例初始化块(即构造代码块,`{ ... }`)。 - 接着执行父类的构造方法(例如`Parent() { ... }`),初始化父类成员变量。 3. **子类实例初始化阶段**: - 父类初始化完成后,JVM执行子类实例初始化块(构造代码块)。 - 然后执行子类的构造方法(例如`Child() { ... }`),初始化子类成员变量。 4. **方法调用顺序**: - 在构造方法或初始化块中调用方法时,如果子类覆盖了父类的方法,则调用子类版本(多态)。 - 例如,在父类构造方法中调用一个被覆盖的方法,会执行子类的实现,但此时子类成员可能尚未初始化(导致潜在问题,如`null`值)[^4]。 #### 代码示例演示 以下是一个简单的Java程序,展示子类实例化时的执行顺序父类`Parent`子类`Child`分别包含静态代码块实例初始化块、构造方法覆盖的方法。 ```java class Parent { static { System.out.println("父类静态代码块"); // 步骤1 } { System.out.println("父类实例初始化块"); // 步骤3 } public Parent() { System.out.println("父类构造方法"); // 步骤4 print(); // 调用方法,多态行为 } public void print() { System.out.println("父类print方法"); } } class Child extends Parent { static { System.out.println("子类静态代码块"); // 步骤2 } { System.out.println("子类实例初始化块"); // 步骤5 } private String name = "Child"; // 子类成员变量 public Child() { System.out.println("子类构造方法"); // 步骤6 print(); // 调用方法 } @Override public void print() { System.out.println("子类print方法: name = " + name); // 多态调用 } } public class Main { public static void main(String[] args) { new Child(); // 创建子类实例 } } ``` **输出结果**: ``` 父类静态代码块 子类静态代码块 父类实例初始化块 父类构造方法 子类print方法: name = null // 注意:此时子类name未初始化 子类实例初始化块 子类构造方法 子类print方法: name = Child // 子类成员已初始化 ``` **输出解释**: - 静态代码块执行父类子类),只执行一次。 - 父类实例初始化块构造方法先于子类执行。 - 在父类构造方法中调用`print()`时,由于多态,执行子类的`print()`方法,但此时子类的`name`尚未初始化(为`null`),显示"name = null"。 - 子类构造方法执行后,`name`被初始化,调用`print()`时显示正确值。 #### 关键注意事项 - **隐式`super()`调用**:如果子类构造方法没有显式调用`super(...)`或`this(...)`,编译器会自动添加`super()`调用父类无参构造方法[^3]。 - **多态行为**:方法调用基于对象的运行时类型(子类),但构造方法中调用方法时,子类成员可能未初始化,需避免。 - **继承链**:在多级继承中,顺序从最顶层父类开始,逐级向下执行[^1]。 - **静态成员**:静态代码块变量在类加载时初始化,优先于实例创建。 通过这个顺序Java确保父类成员被正确初始化后,再处理子类逻辑,避免数据不一致[^4]。如果您有具体代码场景,我可以进一步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值