在Java中代码块指的是使用”{}”括起来的代码称为代码块。代码块一共分为4种:局部代码块,静态代码块,同步代码块,构造代码块。

1、局部代码块

局部代码块就是定义在方法体内部的代码块。

public class CodeBlockTest {
    public static void main(String[] args) {
        int i;
        {
            i=10;
            System.out.println("局部代码块"+i);
            int j=20;
            System.out.println("局部代码块"+j);
        }
        System.out.println(i);
        //Cannot resolve symbol 'j'
        //System.out.println(j);
    }
}

可以看到,在局部代码块中声明的变量,只能在局部代码块中进行访问。局部代码块可以操作非局部代码块的变量,但是非局部代码块不能访问局部代码块的变量。这就起到了很好的分隔,就可以用来限制局部变量的生命周期,及早释放,提高内存利用率。如果有多个局部代码块,则按照它们定义的先后顺序执行。

2、静态代码块

静态代码块就是在类中用static关键字修饰的代码块,它不能出现在方法体或者代码块内,我在上一篇的Static关键字中也记录了静态代码块的使用,所以就把那里的例子引用过来了。

被static修饰的代码块也叫静态代码块,会随着JVM加载类的时候而加载这些静态代码块,并且会自动执行。它们可以有多个,可以存放在于该类的任何地方(不能放在方法内部)。JVM会按照它们的先后顺序依次执行它们,而且每个静态代码块只会被初始化一次,不会进行多次初始化。

简单示例:

public class Person{

    static {
        System.out.println("Person类静态块");
    }

    public Person() {
        System.out.println("Person类构造器");
    }

    public static void main(String[] args) {
        new Son();
        System.out.println("-------");
        new Son();
    }
}

class Son extends Person{
    static {
        System.out.println("Son类静态块");
    }

    public Son() {
        System.out.println("Son类构造器");
    }
}

运行结果:

从运行结果分析:首先运行main()方法,然后JVM就会加载类,因为Son类继承了Person类,所以会先加载父类Person类,再去加载子类Son。由于静态代码块会随着类的加载而加载,所以先输出父类中静态代码块内容"Person类静态块",然后输出子类中静态代码块内容"Son类静态块"。加载完类之后执行main()方法内容,先new了第一个Son实例,由于子类构造器中默认调用了super(),所以先输出父类构造器的内容,再输出子类构造器的内容。之后又new了第二个Son实例,却是输出的构造器的内容,说明static静态块只加载了一次。结论:静态代码块是先加载父类的静态代码块,然后再加载子类静态代码块,是随着类的加载而加载,而且只会加载一次。

补充:因为入口main()是个方法,也需要用类去调用,所以类的加载优先级>main()方法。

3、同步代码块

是使用synchronized关键字修饰的普通代码块(其只能用在方法内部)。其作用在多线程的环境下,对共享数据进行加锁, 从而实现线程同步,是一种多线程保护机制。

public void show(){
    synchronized (obj){
        System.out.println("同步代码块");
    }
}

4、构造代码块

直接在类中用"{}"定义且不加任何关键字的代码块成为构造代码块。

public class CodeBlockTest {

    {
        System.out.println("构造代码块...");
    }

    public CodeBlockTest() {
        System.out.println("无参构造器...");
    }

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

运行结果:

从运行结果容易看出,在创建对象时,构造代码块才会被执行,而且优先于构造方法执行(这里和构造块写前写后没关系,将构造块写在构造方法后面也是一样的结果)。而且每当有对象被创建的时,都会执行构造代码块。如果存在多个构造代码块,则执行顺序按照定义顺序依次执行。

构造代码块的作用:可以用来初始化实例变量和实例环境(即创建对象的必要条件),这样不仅可以减少代码量,同时也可以增强程序的可读性。

注意:构造代码块并不是真正的在构造方法之前执行的,JVM在编译的时候会把构造代码块插入到每个构造函数的最前面,构造代码块随着构造方法的执行而执行,如果某个构造方法调用了其他的构造方法,那么构造代码块不会插入到该构造方法中以免构造代码块执行多次。我们可以从编译生成的class文件可以看出来。

5、代码块的执行顺序

上面讲述了四种代码块的基本信息,然后我们来看一下四种代码块的执行顺序。

public class CodeBlockTest {

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

    {
        System.out.println("构造代码块...");
    }

    public CodeBlockTest() {
        System.out.println("无参构造器...");
    }

    public void show(){
        {
            System.out.println("局部代码块...");
        }
    }

    public static void main(String[] args) {
        System.out.println("main()方法运行");
        new CodeBlockTest().show();
        System.out.println("----------");
        new CodeBlockTest().show();
    }
}

打印结果:

执行顺序(优先级从高到低):静态代码块>mian()方法>构造代码块>构造方法>局部代码块。其中静态代码块只执行一次。构造代码块和局部代码块再每次创建对象是都会执行。

夯实Java基础(八)——代码块的更多相关文章

  1. Java基础(basis)-----代码块详解

    1.静态代码块 格式: static{ 内容..... } 随着类的加载而加载,而且只被加载一次 多个静态代码块之间按照顺序结构执行 优先其他各种代码块以及构造函数先执行 静态的代码块中只能执行静态的 ...

  2. Java基础学习-代码块

    /*代码块: * 用{}修饰的代码 * 1.局部代码块:控制变量,存在方法中,控制变量的生命周期(作用域) * 2.构造代码块:提取构造方法中的共性,每次创建对象,都会执行,并且在构造方法执行之前执行 ...

  3. 夯实Java基础系列7:一文读懂Java 代码块和执行顺序

    目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...

  4. 夯实Java基础系列7:Java 代码块和执行顺序

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  5. 【Java基础】2、Java中普通代码块,构造代码块,静态代码块区别及代码示例

    Java中普通代码块,构造代码块,静态代码块区别及代码示例.Java中普通代码块,构造代码块,静态代码块区别及代码示例 执行顺序:静态代码块>静态方法(main方法)>构造代码块>构 ...

  6. 夯实Java基础系列目录

    自进入大学以来,学习的编程语言从最初的C语言.C++,到后来的Java,. NET.而在学习编程语言的同时也逐渐决定了以后自己要学习的是哪一门语言(Java).到现在为止,学习Java语言也有很长一段 ...

  7. 夯实Java基础系列5:Java文件和Java包结构

    目录 Java中的包概念 包的作用 package 的目录结构 设置 CLASSPATH 系统变量 常用jar包 java软件包的类型 dt.jar rt.jar *.java文件的奥秘 *.Java ...

  8. 夯实Java基础系列6:一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别!

    目录 抽象类介绍 为什么要用抽象类 一个抽象类小故事 一个抽象类小游戏 接口介绍 接口与类相似点: 接口与类的区别: 接口特性 抽象类和接口的区别 接口的使用: 接口最佳实践:设计模式中的工厂模式 接 ...

  9. 夯实Java基础系列9:深入理解Class类和Object类

    目录 Java中Class类及用法 Class类原理 如何获得一个Class类对象 使用Class类的对象来生成目标类的实例 Object类 类构造器public Object(); register ...

  10. 夯实Java基础系列10:深入理解Java中的异常体系

    目录 为什么要使用异常 异常基本定义 异常体系 初识异常 异常和错误 异常的处理方式 "不负责任"的throws 纠结的finally throw : JRE也使用的关键字 异常调 ...

随机推荐

  1. CentOS 7编译安装Redis

    安装编译相关依赖 CentOS/Fedora yum install gcc gcc-c++ cmake tcl 下载Redis源码包 curl -o redis-4.0.10.tar.gz http ...

  2. Android 上传开源项目到 jcenter 实战踩坑之路

    本文微信公众号「AndroidTraveler」首发. 背景 其实 Android 上传开源项目到 jcenter 并不是一件新鲜事,网上也有很多文章. 包括我本人在将开源项目上传到 jcenter ...

  3. 学习体验centos7 下根目录扩容操作(步骤详细!!!)

    转自  苗尼玛乔 感谢你!

  4. C#简单的连接数据库

  5. Java多线程(2)线程锁

    多线程访问同一个资源进行读写操作,就很容易出一些问题(比如我们常见的读者写者,生产者消费者模型)所以我们会选择对他们设置信号量或者加锁,来限制同一个时刻只有一个线程对某个对象进行操作. 多线程是一个蛮 ...

  6. navicat远程连接mysql10060

    navicat连接mysql时,出现2003-Can't connect to MySql server on '47.106.228.160'(10060"Unknow error&quo ...

  7. 基础数据类型,格式化输出,以及for循环的使用

    基础数据类型总览 int :数字类型,可以+-*/等等操作 str:字符串类型,存储少量的数据,+*int 切片等 bool :里面包含True,False这两种值,用来判断真假. list :列表 ...

  8. 职业生涯之完成OCM考试后的感想

    背景知识:关于OCM认证,百科是这样描述的: Oracle Certified Master(OCM) 大师认证资质是Oracle认证的最高级别.此认证是对技术.知识和操作技能的最高级别的认可.Ora ...

  9. scrapy实战7爬取搜狗微信:

    爬取微信热门文章标题,内容,内容地址,微信公众号,公众号地址,发布日期等 如图 源码地址:https://github.com/huwei86/sougouweixin

  10. MyBatis 核心配置综述之Executor

    目录 MyBatis四大组件之 Executor执行器 Executor的继承结构 Executor创建过程以及源码分析 Executor接口的主要方法 Executor 的现实抽象 上一篇我们对Sq ...