Java——代码块

前言


在程序编写之中可以直接使用{...}定义的一段语句就是代码块。根据代码块的位置以及关键字的不同可以分为4种:普通代码块、构造块、静态块以及同步代码块(多线程相关)。下面将先介绍前3种以及Java类的初始化顺序:

  • 普通代码块
  • 构造块
  • 静态块
  • Java类的初始化顺序
    • 对于一个类(没有继承)的初始化情况
    • 对于有继承的情况
  • 普通代码块



    写在方法里面的代码块就是普通代码块

    public static void main(String args[]){
      {
        int num = 0;
      }
      int num=100;
    }

    {...}表示的是一个作用域,内部定义的变量的可以起作用的范围仅在{...}这个范围内。

    上面代码中{int num=0;}的num在离开{...}后就被销毁了,于是可以在外部又可以定义int num=100

    若是写成以下:

    public static void main(String args[]){
      int num=100;
      {
        int num = 0;    //报错:Duplicate local variable num
      }
    }

    因为外部也存在num这个变量,且有效。所以,这样定义会出错。

    普通代码块的作用就是为了防止在方法中编写代码过多,产生变量重名,于是对一个方法中的代码进行局部的分割。但是建议一个方法中的代码不要太长,尽量不使用普通代码块

    构造块


    如果将一个代码块放在类里面,那么就是一个构造块。

    构造块的作用是为了给对象进行初始化。我们知道构造函数的作用也是为了给对象进行初始化,那么这两者有什么区别呢?

    public  class Student {
        private String name;
        private int age;
    
        //无参构造函数
        public Student() {
            System.out.println("constructor with no args ");
            System.out.println("name:"+this.name + " age:"+this.age);
            this.name = "no name";
            this.age = 18;
        }
    
        //有参构造函数
        public Student(String name, int age){
            System.out.println("constructor with args");
            System.out.println("name:"+this.name + " age:"+this.age);
            this.name = name;
            this.age = age;
        }
    
        //构造块
        {
            System.out.println("constructor block ");
            name = "cbname";
            age = 20;
        }
    
        public static void main(String[] args) {
            new Student();
            System.out.println("==========");
            new Student("sakura", 19);
        }
    }
    /*
    output:
    constructor block
    constructor with no args
    name:cbname age:20
    ==========
    constructor block
    constructor with args
    name:cbname age:20
    */

    可以看出每次创建对象时,都会调用一次构造块,并且构造块的优先于构造函数执行。有对象的创建,才会调用构造快,类是不能调用构造块的。

    构造块与构造函数的区别在于:每个对象被构造块初始化的那部分变量拥有的初始值是一样的,构造块对所有对象的效果是一样的。然而每个对象可能会使用不同构造函数,不同的构造函数初始化对象的方式是不同的

    静态块


    使用static修饰的代码块就叫做静态代码块或者直接叫静态块。

    前面在介绍static关键字(可以回顾查看)时,介绍了一部分static修饰代码块的知识。

    • 静态块在类加载时执行,且只会执行一次执行顺序优先主函数、构造函数和构造块
    • 静态代码块主要用于初始化类中的static属性(类属性),而构造块是初始化对象中的属性
    • 一个类中可以有多个静态代码块, 执行顺序依照静态代码块的声明顺序。静态代码块可以在类的任意位置定义,在方法中不可以声明静态块

    Java类的初始化顺序


    对于一个类(没有继承)的初始化情况


    public  class Student {
        private String name="no name";
        private int age=18;
        private static int id=1;
        //无参构造函数
        public Student() {
            System.out.println("======");
            System.out.println("无参构造函数");
            System.out.println("姓名:"+name+" 年龄:"+age);
        }
    
        //有参构造函数
        public Student(String name, int age){
            System.out.println("======");
            System.out.println("有参构造函数");
            System.out.println("姓名:"+this.name+" 年龄:"+this.age);
            this.name = name;
            this.age = age;
            System.out.println("姓名:"+this.name+" 年龄:"+this.age);
        }
    
        //构造块
        {
            System.out.println("======");
            System.out.println("构造块");
            System.out.println("姓名:"+this.name+" 年龄:"+this.age);
            this.name = "cbname";
            this.age = 18;
        }
    
        //静态代码块
        static {
            System.out.println("======");
            System.out.println("静态块");
            System.out.println("静态变量id="+id);
        }
    
        public static void main(String[] args) {
            System.out.println("======");
            System.out.println("主方法");
            new Student();
            new Student("小王",20);
        }
    }
    
    /*
    output:
    ======
    静态块
    静态变量id=1
    ======
    主方法
    ======
    构造块
    姓名:no name 年龄:18
    ======
    无参构造函数
    姓名:cbname 年龄:18
    ======
    构造块
    姓名:no name 年龄:18
    ======
    有参构造函数
    姓名:cbname 年龄:18
    姓名:小王 年龄:20
    */

    对于一个类而言:

    静态代码块、构造代码块、构造函数和主函数的执行顺序为:

    静态代码块>主函数>构造代码块>构造函数

    在加上静态属性、普通属性,他们的初始化执行顺序就为:

    静态变量、静态代码块 > 主函数 > 指定初始值的属性 > 构造代码块 > 构造函数

    对于有继承的情况


    class Person{
        private String name="Person没有名字";
        private int age=10;
        private static int id=1;
        //无参构造函数
        public Person() {
            System.out.println("======");
            System.out.println("Person无参构造函数");
            System.out.println("Person 姓名:"+this.name+" 年龄:"+this.age);
        }
    
        //构造块
        {
            System.out.println("======");
            System.out.println("Person 构造块");
            System.out.println("Person 姓名:"+this.name+" 年龄:"+this.age);
            this.name = "pcbname";
            this.age =11 ;
        }
    
        //静态代码块
        static {
            System.out.println("======");
            System.out.println("Person 静态块");
            System.out.println("Person 静态变量id="+id);
        }
    }
    public  class Student extends Person{
        private String name="Student没有名字";
        private int age=18;
        private static int id=2;
        //无参构造函数
        public Student() {
            //自动调用父类的无参构造函数 super();
            System.out.println("======");
            System.out.println("Student无参构造函数");
            System.out.println("Student 姓名:"+this.name+" 年龄:"+this.age);
        }
    
        //有参构造函数
        public Student(String name, int age) {
            //自动调用父类的无参构造函数 super();
            System.out.println("======");
            System.out.println("Student有参构造函数");
            System.out.println("Student 姓名:"+this.name+" 年龄:"+this.age);
            this.name = name;
            this.age = age;
        }
    
        //构造块
        {
            System.out.println("======");
            System.out.println("Student 构造块");
            System.out.println("Student 姓名:"+this.name+" 年龄:"+this.age);
            this.name = "scbname";
            this.age = 19;
        }
    
        //静态代码块
        static {
            System.out.println("======");
            System.out.println("Student 静态块");
            System.out.println("Student 静态变量id="+id);
        }
    
        public static void main(String[] args) {
            System.out.println("======");
            System.out.println("主方法");
            System.out.println("\n--------第一次创建Studet对象--------");
            new Student();
            System.out.println("\n--------第二次创建Studet对象--------");
            new Student("小夏",20);
        }
    }
    /*
    ======
    Person 静态块
    Person 静态变量id=1
    ======
    Student 静态块
    Student 静态变量id=2
    ======
    主方法
    
    --------第一次创建Studet对象--------
    ======
    Person 构造块
    Person 姓名:Person没有名字 年龄:10
    ======
    Person无参构造函数
    Person 姓名:pcbname 年龄:11
    ======
    Student 构造块
    Student 姓名:Student没有名字 年龄:18
    ======
    Student无参构造函数
    Student 姓名:scbname 年龄:19
    
    --------第二次创建Studet对象--------
    ======
    Person 构造块
    Person 姓名:Person没有名字 年龄:10
    ======
    Person无参构造函数
    Person 姓名:pcbname 年龄:11
    ======
    Student 构造块
    Student 姓名:Student没有名字 年龄:18
    ======
    Student有参构造函数
    Student 姓名:scbname 年龄:19
    */

    观察代码结果,分析,对于有继承关系的类,初始化顺序按如下进行:

    1. 执行父类的静态代码块,并初始化父类静态成员变量

      2. 执行子类的静态代码块,并初始化子类静态成员变量

      3. 执行父类的构造代码块,执行父类的构造函数,若普通成员变量指定了初始值则先执行初始值的赋值,然后返回执行构造函数

      4.执行子类的构造代码块,执行子类的构造函数,若普通成员变量指定了初始值则先执行初始值的赋值,然后返回执行构造函数

    小结


    本文介绍的三种代码块,普通块和构造块都不建议使用,静态块可以使用用于初始化静态变量。

    理清Java程序初始化的执行顺序可以很清楚地掌握程序的执行过程。

    对一个类而言,静态变量和静态代码块> 主函数 > 指定初始值的属性 > 构造代码块 > 构造函数

    对于有继承的来说,父类静态块和静态变量 > 子类静态块和静态变量 > 父类指定初始值的属性 > 父类构造块 > 父类构造函数 > 子类指定初始值的属性 > 子类构造块 > 子类构造函数

    参考博客:

    https://www.cnblogs.com/Qian123/p/5713440.html

    原文地址:https://www.cnblogs.com/myworld7/p/10053367.html

    时间: 2024-10-04 09:20:00

    Java——代码块的相关文章

    java代码块的理解

    最近在复习java基础,在看到java代码块的时候,忽然发现自己貌似对于java代码块一无所知,于是赶紧对着一些资料实战演练了一把. 对于java代码块,不难根据名称看出其实就是一些java语句的集合,以{}的形式出现,共有4中形式: 1.类的方法体 这是我们最常见的一种java代码块,形式如下: 1 public class Boke { 2 public void say(){ 3 System.out.println("我就是代码块的内容啦"); 4 } 5 } say的方法体{

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

    目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块简介 Java代码块使用 局部代码块 构造代码块 静态代码块 Java代码块.构造方法(包含继承关系)的执行顺序 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github

    08 java代码块的概述和分类

    08.01_面向对象(代码块的概述和分类) A:代码块概述 在Java中,使用{}括起来的代码被称为代码块. B:代码块分类 根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解). 局部代码块:只要是和局部有关系的,都是和方法有关系的 局部变量:在方法声明上或者在方法内部 构造代码块与类变量谁在前先加载谁 ,所有静态的东西(静态方法和静态变量都是)只加载一次,就是在类文件加载的时候加载,类文件释放的时候释放,加载顺序为,静态,–>–>构造代码块或局部变量

    Java 代码块,普通代码块,构造代码块,静态代码块

    学习Java中… 刚刚学到了Java的代码块,虽然很简单 还是记下吧! 左音 2016-03-16 ----------------- // 执行优先级:静态代码块 > mian方法 > 构造代码块 > 构造方法 // 静态代码块不论是否实例化都会执行一次,不会重复执行 // 构造代码块实例化时执行 1.普通代码块 // 普通代码块在方法或语句中 1 public class CodeBlock { 2 3 public static void main (String[] args)

    java代码块执行顺序

    1.测试类 public class Demo extends SuperDemo { //静态代码块 static{ System.out.println("this is static block"); } //普通代码块 { System.out.println("this is normal block"); } //默认构造函数 public Demo(){ System.out.println("this is demo constructor

    java代码块 静态、非静态

    Java虚拟机的内存分区:Java栈.堆.方法区.本地方法栈.PC寄存器.还有一个常量池的概念,虚拟机会为每种类型分配一个常量池,而不是实例. 例如有一个类有很多子类,那么在父类定义的final变量,在子类是不能被改变的.可以说明是在类型上分配的. 被static修饰的变量或者方法是属于类本身,而不属于类的实例.在类被加载进虚拟机的时候就已经初始化了,他存在与方法区,方法区和堆区的时候是共享的,因此他被设计为线程安全的.假设同时有两个线程都企图访问一个名为A的类,而这个类还没有被转入虚拟机,此时

    08-02 Java 代码块,代码块执行的先后顺序问题

    代码块 /* 代码块:在Java中,使用{}括起来的代码被称为代码块. 根据其位置和声明的不同,可以分为 局部代码块:局部位置,用于限定变量的生命周期. 构造代码块:在类中的成员位置,用{}括起来的代码.每次调用构造方法执行前,都会先执行构造代码块. 作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化. 静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了. 作用:一般是对类进行初始化. 面试题? 静态代码块,构造代码块,构造方法的执行顺序? 静态代码块 -

    java代码块(转)

    1 //普通代码块:在方法或语句中出现的{}就称为普通代码块.普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定--“先出现先执行” 2 public class CodeBlock01{ 3 public static void main(String[] args){ 4 5 { 6 int x=3; 7 System.out.println("1,普通代码块内的变量x="+x); 8 } 9 10 int x=1; 11 System.out.println("

    类加载联想java代码块1

    今天想做spring的类加载的实验,所以恶补下java类加载的知识,看了深入理解java虚拟机211页的示例中的静态代码块,突然想到疯狂java里面总结非静态代码块总结得很好,当时自己看了之后感觉豁然开朗,但是现在只有一点印象,只记得是好像和构造方法有关,编译器处理的时候会优化.而这个非静态代码块的作用的印象,真是一点都没有啊. 学习就是这样,不总结,不温习,别说知新,永远是用的时候疲于学习,用完一无所有,所以我觉得每天总结下自己的学习,作为日志博客记载.不求人家共鸣,只求自己写的自己回头看的,