Java中的代码块

代码块

1. 代码块基本概念

  • 代码块:又称为初始化块,属于类中的成员【即是类的一部分】,类似于方法,将逻辑语句封装在方法体中,用 {} 包围起来。
  • 基本用法:
    在这里插入图片描述
  • 代码块的理解:

(1)相当于另外一种形式的构造器(是对构造器的补充机制),可以做初始化操作;
(2)使用场景,如果多个构造器中都有重复的语句,可以抽取到代码块中,提高代码的复用性,相当于对构造器的重载;
(3)代码块调用的顺序优先于构造器。

二、代码块使用注意事项和细节

  • 注意事项:

1. 类什么时候被加载

(1)创建类的对象实例时(new),类会被加载。
(2)存在继承关系,当创建子类对象实例时,其所有上级父类也会被加载;并且父类先被加载,越上级的父类,越先被加载。
(3)当使用类的静态成员时(静态属性,静态方法),类会被加载。
(4)注意,类的加载是在内存的方法区中。

2. 什么是代码块

(1)static 关键字修饰的代码块也叫静态代码块,它的作用就是对类进行初始化;它伴随着类的加载而执行,并且只会执行一次。
(2)没有关键字修饰的代码块也叫普通代码块,它相当于是构造器的补充机制;每当我们创建一个类的对象时,普通代码块就会被调用一次;如果只是直接使用类的静态成员,没有创建对象,它不会被调用;注意,普通代码块的调用与类的加载没有关系。

3. 创建一个对象时,在一个类中各属性和方法被虚拟机调用的顺序

(1)首先是调用静态代码块和进行静态属性初始化 (注意,调用静态代码块和静态属性初始化的优先级一样,若有多个静态代码块和静态属性初始化同时存在,则按他们定义的顺序使用),这一步是在类的加载时进行的。
(2)其次是正式在堆内存中创建一个对象空间,并调用普通代码块和进行普通属性的初始化 (注意,调用普通代码块和普通属性初始化的优先级一样,若有多个普通代码块和普通属性初始化同时存在,则按他们定义的顺序使用)。
(3)最后是调用类中的构造方法。
(4)补充:对于普通的静态方法,不会被虚拟机自动执行,啥时候被调用,啥时候执行。

  • 代码举例说明:

public class CodeBlockDetail02 {
    public static void main(String[] args) {

        A a = new A();// 输出如下:
        // (1) A 静态代码块01 (2) getN1被调用...
        // (3) A 普通代码块01 (4) getN2被调用...
        // (5) A() 构造器被调用
    }
}

class A {

	// 普通代码块
    { 
        System.out.println("A 普通代码块01");
    }

    // 普通属性的初始化
    private int n2 = getN2();

    // 静态代码块
    static { 
        System.out.println("A 静态代码块01");
    }

    // 静态属性的初始化
    private static int n1 = getN1();

    // 静态方法
    public static int getN1() {
        System.out.println("getN1被调用...");
        return 100;
    }

    // 普通方法/非静态方法
    public int getN2() { 
        System.out.println("getN2被调用...");
        return 200;
    }

    // 无参构造器
    public A() {
        System.out.println("A() 构造器被调用");
    }
}

4. 存在继承关系时,调用普通代码块和普通属性初始化的说明

(1)在构造器/构造方法的最前面其实隐含了 super()语句,还有调用普通代码块和普通属性的初始化的语句,最后才是构造器自己的语句。
(2)我们这里所说的普通属性的初始化,指的是属性在默认初始化后进行的,在构造器内的初始化(这一部分的概念是在面对对象基础部分学习的)。

  • 代码举例说明:

public class CodeBlockDetail03 {
    public static void main(String[] args) {
        new BBB();
        //(1) AAA的普通代码块 (2) AAA() 构造器被调用
        //(3) BBB的普通代码块 (4) BBB() 构造器被调用
    }
}

// 父类
class AAA { 

    // 普通代码块
    {
        System.out.println("AAA的普通代码块");
    }

    // 构造器
    public AAA() {
        //(1) super()
        //(2) 调用本类的普通代码块和普通属性的初始化
        System.out.println("AAA() 构造器被调用....");
    }
}

// 子类
class BBB extends AAA  {

    // 普通代码块
    {
        System.out.println("BBB的普通代码块...");
    }

    public BBB() {
        // (1)super()
        // (2)调用本类的普通代码块和普通属性的初始化
        System.out.println("BBB() 构造器被调用....");
    }
}

5. 存在继承关系时,创建一个子类对象,各个方法和属性被虚拟机调用的顺序

  • 首先是在类加载时,调用静态代码块和静态属性的初始化。
    (1)父类的静态代码块和静态属性(优先级一样,按定义顺序执行)。
    (2)子类的静态代码块和静态属性(优先级一样,按定义顺序执行)。
  • 其次是在堆内存中创建对象空间,调用普通代码块和普通属性的初始化,调用构造方法。
    (3)在构造器中调用父类的普通代码块和普通属性的初始化(优先级一样,按定义顺序执行)。
    (4)执行父类的构造器其余的方法。
    (5)在构造器中调用子类的普通代码块和普通属性的初始化(优先级一样,按定义顺序执行)。
    (6)执行子类的构造器其余的方法。
  • 代码举例说明:

public class CodeBlockDetail04 {
    public static void main(String[] args) {
        // 说明
        // (1) 进行类的加载
        //   1.1 先加载 父类 A02 ;1.2 再加载子类 B02
        // (2) 创建对象空间
        //   2.1 从子类的构造器开始
        new B02();// 创建对象
    }
}

//父类
class A02 { 
	
    static {
        System.out.println("A02的一个静态代码块..");//(2)
    }

    {
        System.out.println("A02的第一个普通代码块..");//(5)
    }

    public int n3 = getVal02();//普通属性的初始化

    public static int getVal01() {
        System.out.println("getVal01");//(1)
        return 10;
    }

    public int getVal02() {
        System.out.println("getVal02");//(6)
        return 10;
    }

	//构造器
    public A02() {
        //隐藏
        //super()
        //普通代码和普通属性的初始化
        System.out.println("A02的构造器");//(7)
    }

}

//子类
class B02 extends A02 { //
    
    static {
        System.out.println("B02的一个静态代码块..");//(4)
    }

    public int n5 = getVal04();

    {
        System.out.println("B02的第一个普通代码块..");//(9)
    }

    public static int getVal03() {
        System.out.println("getVal03");//(3)
        return 10;
    }

    public int getVal04() {
        System.out.println("getVal04");//(8)
        return 10;
    }
    
    // 构造器
    public B02() {
        //隐藏了
        //super()
        //普通代码块和普通属性的初始化
        System.out.println("B02的构造器");//(10)
    }
}

总结

  • 本文是小白博主在学习B站韩顺平老师的Java网课时整理总结的学习笔记,在这里感谢韩顺平老师的网课,如有有兴趣的小伙伴也可以去看看。
  • 本文详细解释了代码块的概念与使用,并深入解释了创建一个对象时的底层流程分析,非常非常重要,希望小伙伴们看后能有所收获!
  • 最后,如果本文有什么错漏的地方,欢迎大家批评指正!一起加油!!我们下一篇博文见吧!
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林二月er

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值