当前位置: 首页 > article >正文

Java 代码块

目录

代码块是什么

普通代码块

构造块

静态块

同步代码块


代码块是什么

代码块:使用 {} 定义的一段代码

根据代码块 定义的位置 和 关键字,代码块可分为以下 四种

普通代码块

构造块

静态块

同步代码块

普通代码块

普通代码块:定义在方法中的代码块

public class Test {
    public static void main(String[] args) {
        {
            int a = 5;
            System.out.println("a: " + a);
        }
        int a = 10;
        System.out.println("a: " + a);

    }
}

运行结果:

普通代码块 中定义的变量 a,不能在 方法 中使用,即 a 在代码块执行完毕时就被销毁了

普通代码块的执行顺序为 顺序执行(在方法中从上往下,先出现,先执行) 

public class Test {
    public static void main(String[] args) {
        int a = 10;
        System.out.println("a: " + a);

        {
            a = 5;
            System.out.println("a: " + a);
        }
    }
}

运行结果:

 

在方法中定义的变量可以在代码块中进行访问和修改

构造块

构造块:定义在中的代码块,也叫做实例代码块

构造代码块一般用于初始化实例成员变量

public class Student {
    private int id;
    private String name;
    private int age;

    public Student() {
        System.out.println("init...");
    }

    // 构造代码块
    {
        id = 1;
        name = "张三";
        age = 19;
        System.out.println("执行构造代码块");
    }

    public void info() {
        System.out.println("id: " + id + " name: " + name + " age: " + age);
    }
    
    public static void main(String[] args) {
        Student student = new Student();
        student.info();
    }
}

运行结果:

 

构造代码块在构造方法之前执行,且与构造代码块的位置无关,无论构造代码块放在哪里,都会先执行构造代码块,再执行构造方法

public class Student {
    private int id;
    private String name;
    private int age;

    public Student() {
        System.out.println("init...");
    }

    // 构造代码块
    {
        id = 1;
        name = "张三";
        age = 19;
        System.out.println("执行构造代码块");
    }

    {
        id = 2;
        System.out.println("再次执行构造方法");
    }

    public void info() {
        System.out.println("id: " + id + " name: " + name + " age: " + age);
    }

    public static void main(String[] args) {
        Student student = new Student();
        student.info();
    }
}

运行结果:

 

当有多个构造代码块时, 编译器会按照定义的先后顺序,将这些构造代码块进行合并,然后按照顺序执行

使用构造方法就可以初始化实例成员变量,为什么还需要使用构造代码块呢?

构造代码块相当于是对构造器的补充

还是上述例子:

public class Student {
    private int id;
    private String name;
    private int age;

    public Student() {
    }

    public Student(int id) {
        this.id = id;
    }

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    // 构造代码块
    {
        id = 1;
        name = "张三";
        age = 19;
        System.out.println("执行构造代码块");
    }

    public void info() {
        System.out.println("id: " + id + " name: " + name + " age: " + age);
    }

    public static void main(String[] args) {
        Student student = new Student();
        student.info();
        Student student1 = new Student(2, "李四");
        student1.info();
        Student student2 = new Student(3, "王五", 18);
        student2.info();
    }
}

运行结果:

 

无论调用哪个构造方法,在每次创建实例时,都会先执行构造代码块,再执行构造方法,因此,若多个构造器中都有重复的语句,就可以将其抽取到构造代码块中,或是在构造代码块中为变量赋默认值

静态块

静态代码块:使用 static 定义的代码块

一般用于初始化静态成员变量

public class Student {
    private int id;
    private String name;
    private int age;
    private static String classRoom;

    public Student() {
    }

    public Student(int id) {
        this.id = id;
    }

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    // 构造代码块
    {
        id = 1;
        name = "张三";
        age = 19;
        System.out.println("执行构造代码块");
    }

    // 静态代码块
    static {
        classRoom = "一班";
        System.out.println("执行静态代码块");
    }

    public void info() {
        System.out.println("id: " + id + " name: " + name + " age: " + age);
    }

    public static void main(String[] args) {
        Student student = new Student();
        student.info();
        Student student1 = new Student(2, "李四");
        student1.info();
        Student student2 = new Student(3, "王五", 18);
        student2.info();
    }
}

运行结果:

我们可以发现:静态代码块在构造代码块之前执行,且只执行了一次

为什么静态代码块只执行了一次呢?

静态代码块一般用于初始化静态成员变量,而静态成员变量类的属性,因此,静态成员变量是在 JVM 进行 类加载 时就为其开辟了空间并进行了初始化,也就是说静态代码块在类加载时就被执行了,后续也就不会被执行了

public class Student {
    private int id;
    private String name;
    private int age;
    private static String classRoom;

    public Student() {
    }

    public Student(int id) {
        this.id = id;
    }

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    // 构造代码块
    {
        id = 1;
        name = "张三";
        age = 19;
        System.out.println("执行构造代码块");
    }


    // 静态代码块
    static {
        classRoom = "一班";
        System.out.println("执行静态代码块");
    }

    static {
        classRoom = "二班";
        System.out.println("再次执行静态代码块");
    }

    public void info() {
        System.out.println("id: " + id + " name: " + name + " age: " + age + " class: " + classRoom);
    }

    public static void main(String[] args) {
        Student student = new Student();
        student.info();
        Student student1 = new Student(2, "李四");
        student1.info();
        Student student2 = new Student(3, "王五", 18);
        student2.info();
    }
}

运行结果:

若类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后顺序,将这些静态代码块进行合并,然后按照顺序执行

即:

静态代码块无论创建多少个对象,都只会执行一次(在类加载时执行)

构造代码块每次创建对象时都会执行(在创建对象时执行)

同步代码块

什么是同步?

在 Java 中,允许多个线程并发执行,当多个线程需要访问和操作同一个资源(共享资源)时,多个线程之间就可能会产生冲突,出现数据不一致或破坏数据完整性的问题。此时就可以使用 同步代码块(synchronized block)来控制多个线程对共享资源的访问,将代码块标记为同步(也就是进行 加锁 操作),保证同一时间只有一个线程能够执行该代码块

在 Java 中一般使用 synchronized 来实现同步代码块

synchronized (Object locker) {

        ...

}

其中 locker 表示加锁的对象, 只有获取到该对象的锁的线程才能继续执行代码块,这个对象可以是任意的 Java 对象

例如:

public class Test {
    private static int count = 0;
    public static void main(String[] args) throws InterruptedException {
        Object locker = new Object();

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                synchronized (locker) {
                    count++;
                }
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                synchronized (locker) {
                    count++;
                }
            }
        });

        t1.start();
        t2.start();
        
        t1.join();
        t2.join();
        System.out.println("count: " + count);
    }
}

同步代码块涉及到很多知识,例如 如何进行加锁、有哪些注意事项、加锁过程中可能会产生哪些问题...

更多关于同步代码块的知识,在这里就不展开讲解了,可以参考之前的文章:

线程安全问题_线程安全的例子-CSDN博客


http://www.kler.cn/a/325657.html

相关文章:

  • 杰发科技AC7801——ADC定时器触发的简单使用
  • Pytest-Bdd-Playwright 系列教程(12):步骤参数 parsers参数解析
  • Java 核心技术卷 I 学习记录九
  • 1+X应急响应(网络)网络流量分析技术:
  • 环形缓冲区 之 STM32 串口接收的实现
  • IDEA2023 SpringBoot整合Web开发(二)
  • vue + echarts 快速入门
  • 【数据结构与算法】Z算法(扩展KMP)(C++和Python写法)
  • MyBatis-Plus如何分页查询?
  • react 函数组件
  • 《程序猿之Redis缓存实战 · 列表类型》
  • DMDSC更换DCR和VOTE磁盘
  • 云计算Openstack Keystone
  • JVM 基础知识(基础组成 )
  • 寻找两个正序数的中位数(C)
  • Json 在线可视化工具,分享几个
  • K8S篇之解析service和ingress区别
  • 深度学习--------------------------------门控循环单元GRU
  • 利用git将项目上传到github
  • 指定PDF或图片多个识别区域,识别区域文字,并导出到Excel文件中
  • 25届秋招总结——保持自信、坚定选择
  • 【C++算法】6.双指针_有效三角形的个数
  • Android 10.0 系统framework层修改第三方app的dpi的属性功能实现
  • mmseqs2蛋白质聚类数据格式转化
  • C++进阶知识1继承
  • 从零预训练一个tiny-llama#Datawhale组队学习Task2