【Java】代码块

一、引入

例如下图中,在语句上下加一个单独的 大括号,这个就叫做 代码块

image-20240417161837954

根据代码块出现的位置不同,我们可以把它分为三类。

1、写在方法中的 局部代码块

2、写在成员位置(方法外,类里面)的 构造代码块

3、使用 static 修饰的 静态代码块


二、局部代码块

1)介绍

局部代码块 这个词语我们需要分为两部分进行解释。

局部:在代码中 局部位置 指的是在 方法里面

代码块:就是刚刚看到的单独的大括号。

因此 局部代码块 合起来就是:写在 方法里面 的一对 单独的大括号,如下图所示。

image-20240417162230849

作用:提前结束变量的生命周期。在之前我们曾经讲过:变量的作用范围,它只在所属的大括号中有效。

而现在,变量 a 是定义在 局部代码块 中的,因此它只能在 局部代码块 里面才能使用 变量a

当代码执行到 左括号 时,变量a 就会从内存中消失了。

image-20240417162625768

这个技术听上去很牛逼,但是现在已经用不了了。我们细品,这个技术最本质的作用就是:节约内存,变量用不到了,我就立马让它消失。

在很久很久以前,计算机硬件不是很发达的时候才会用到 局部代码块。例如以前的游戏机

image-20240417162230849

它的内存很小很小,其中有一个很经典的游戏,它的大小只有 128k,这么小的内存为什么还有那么丰富的剧情呢?

image-20240417162625768

它里面用到了很多编程思想,其中有一个就是我们今天说的局部代码块 的思想,用完了就让你立马回收,不会让你浪费一丁点内存空间。

虽然这个游戏不是Java写的,但是用完后 立马回收 的思想 就跟我们现在的 局部代码块 是一致的。

但是,随着现在计算机的硬件发展的越来越好,这个技术已经渐渐的淘汰了。现在电脑内存,少有十几个G,服务器的内存就更大了,你多定义几个变量,浪费几个字节的空间,都无所谓。

因此局部代码块我们了解一下就可以了。


2)代码示例

{
    int a = 10;
} // 当代码执行到这里时,变量a就从内存中消失了
System.out.println(a); // 一旦消失,这行代码就会报错

二、构造代码块

1)介绍

例如在下图中,有两个构造方法:第一个是空参构造,第二个是带全部参数的构造

在这两个构造方法中都打印了一句话:"开始创建对象了",此时打印语句在两个构造方法中就重复了。

此时就可以将重复的代码抽取出来,将它写在构造代码块中。

image-20240417163805516

此时你就会发现,构造代码块 其实就是写在 成员位置 的代码块。

当我们要创建 Student对象 的时候,它会优先于 构造方法 执行。所以在以前,我们可以把多个构造方法中重复的代码写在 构造代码块 中。


2)代码示例

下面这段代码,无论是使用 无参构造 还是 全参构造 创建对象,都会打印 "开始创建对象了"

//构造代码块:
//1.写在成员位置的代码块 就是 构造代码块
//2.作用:可以把多个构造方法中重复的代码抽取出来
//3.执行时机:我们在创建本类对象的时候会先执行 构造代码块,再执行 构造方法。构造代码块它是优先于构造方法执行的。
{
    System.out.println("开始创建对象了");
}

public Student() {
    System.out.println("空参构造");
}

public Student(String name, int age) {
    System.out.println("有参构造");
    this.name = name;
    this.age = age;
}

这个技术现在其实也渐渐的淘汰了。

其实就是因为这种写法它不够灵活,假设现在写了第三个构造。

public Student(String name) {
    System.out.println("有参构造");
    this.name = name;
}

使用第三个构造方法创建对象的时候,我不想执行 "开始创建对象了" 这句话,是没有办法的,因为 构造代码块 必定会优先于 构造方法 执行。


3)解决问题

如果三个构造方法中,有两个构造方法中有重复的代码,我们该如何解决呢?

方法一:此时我们会把重复的代码写在一个构造方法中,然后在其他的构造方法中就不需要再写了,我们可以通过 this关键字 去调用本类的其他构造。如果不知道 name、age 的值是多少,只需要在构造的时候给它一个默认值就可以了。

image-20240417165805998

方法二:将重复的代码抽取成一个方法,在构造方法中想要用到,直接调用方法就行了。

image-20240417165923864

因此,由于 构造代码块 不灵活,如果构造方法中有重复的代码,我们大部分使用的还是上面两种方式。对于 构造代码块 来说,我们只需要了解一下就行了。


三、静态代码块

静态代码块是一个重点,需要大家掌握,在以后会大量用到。

1)介绍

静态代码块 其实就是在 构造代码块 前面加上了 static 静态关键字。

特点:需要通过 static关键字 修饰,随着类的加载而加载,并且自动触发、只执行一次。

构造代码块是每次创建对象的时候,它一定都会执行。你创建一个对象,它执行1次;你创建十个对象,它执行10次。

但是静态代码块不一样,它只执行一次,而且它是随着类的加载而加载的。当这个类加载到内存中的时候,静态代码块中的代码它就会自动的执行一次。

使用场景:在类加载的时候,做一些数据初始化的时候使用。


2)代码实现

//执行时机:
//随着类的加载而加载的,并且只执行一次。
static {
    System.out.println("静态代码块执行了");
}

执行下段代码,可以发现创建了两个对象,但是只打印了一句 "静态代码块执行了",并且是在一开始的时候执行的。

//创建对象
Student s1 = new Student();
Student s2 = new Student("zhangsan",23);

3)使用场景

使用场景:在类加载的时候,做一些数据初始化的时候使用。

例如之前我们写的 学生管理系统,我们发现,每次程序运行的时候,我们都要去注册用户名、添加学生信息。。。等很多操作,感觉太麻烦了。那么能不能在程序刚开始运行的时候,就有一些初始化的数据呢?

此时我们就可以通过静态代码块去完成。

// 由于静态中只能用静态,因此集合也需要使用 static 修饰
static ArrayList<User> list = new ArrayList<>();
static {
    // 添加一些用户信息
    list.add(new User("zhangsan", "1234qwer", "1322323", "234739817493749036"));
    list.add(new User("lisi", "1234qwer", "1322323", "234739817493749036"));
    ...
}

4)解决问题

此时有的同学会说:这些功能我不使用 静态代码块 好像也能做到,如下代码。

public class App2 {
    public static void main(String[] args) {
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("zhangsan", "1234qwer", "1322323", "234739817493749036"));
        list.add(new User("lisi", "1234qwer", "1322323", "234739817493749036"));
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("欢迎来到学生管理系统");
            System.out.println("请选择操作:1登录 2注册 3忘记密码");
            String choose = sc.next();
            switch (choose) {
                case "1" -> login(list);
                case "2" -> register(list);
                case "3" -> forgetPassword(list);
                case "4" -> {
                    System.out.println("谢谢使用,再见");
                    System.exit(0);
                }
                default -> System.out.println("没有这个选项");
            }
        }
    }
}

这种写法确实也可以实现数据初始化,但是有弊端,由于上面这样写是将代码写在方法中的,一旦是方法,就有可能会被别人反复的去调用,那么这个集合在内存中可能就会有多个,这些用户信息也可能会反复的进行添加。

我们可以来做一个测试。首先我们需要知道:main方法 其实也是可以被我们手动调用的。

public class App2 {
    public static void main(String[] args) {
        // 例如这里调用多次上面 App2 中的 main方法。这就是这种做法的弊端
        App2.main(null);
        App2.main(null);
        App2.main(null);
        App2.main(null);
        App2.main(null);
    }
}

因此,如果我们以后想要做一些 数据初始化,并且这些数据初始化的代码你只想执行一次,就将它写在静态代码块中就行了。


四、总结

1、代码块的分类

写在方法中的 局部代码块

写在成员位置(方法外,类里面)的 构造代码块

使用 static 修饰的 静态代码块

2、局部代码块的作用

提前结束变量的生命周期(已淘汰,了解即可)

3、构造代码块的作用

抽取构造方法中的重复代码(不够灵活,了解即可)

4、静态代码块的作用

数据的初始化(重点)

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值