Java---韩顺平代码块笔记(有个人理解)

四、代码块

4.1、基本介绍

代码块又称为初始化块,属于类中的成员(即 是类的一部分),类似于方法,将逻辑语句封装在方法体中,通过{}包围起来

但是和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显示调用而是加载类时,或创建对象时隐式调用。

  • 基本语法:

    • [修饰符]{
          代码体
      };
    • 说明注意:

      • 修饰符 可选填,但是 写的话也只能写static

      • 代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫非静态代码块。

      • 逻辑语句可以为任何逻辑语句。

      • ”号可以写,也可以不写!

    • 使用场景:

      • 相当于另外一种形式的构造器,可以做初始化操作

      • 如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性。

      • 代码样例:(我想每个构造函数里面都去输入开场白,即可使用代码块的形式进行初始化操作)

      public class text4 {
          public static void main(String[] args) {
              new Moive("送你一朵小红花");
              System.out.println("-------------------------------------");
              new Moive("飞驰人生",100);
          }
      }
      ​
      ​
      class Moive{
          private String name;
          private double price;
          private String director;
      ​
          //代码块初始化
          {
              System.out.println("电影屏幕打开");
              System.out.println("电影广告。。。。。");
              System.out.println("电影开始播放。。。。。。");
          };
      ​
          public Moive(String name) {
      ​
              this.name = name;
          }
      ​
          public Moive(String name, double price) {
              this.name = name;
              this.price = price;
          }
      ​
          public Moive(String name, double price, String director) {
              this.name = name;
              this.price = price;
              this.director = director;
          }
      }
      
      		

4.2、代码块细节

4.2.1、细节1

static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行的,因为类只会加载一次,所以静态代码块只会执行一次。如果是普通代码块,每创建一个对象,就执行。

  • 代码示例:

    public class text05 {
        public static void main(String[] args) {
            AA aa1 = new AA();
            AA aa2 = new AA();
        }
    }
    ​
    class AA{
        static{
            System.out.println("AA类的静态代码块,,,,,,,,,,");
        };
        {
            System.out.println("AA的普通代码块。。。。。。。。。。。");
        };
    }

    输出:

    AA类的静态代码块,,,,,,,,,, 
    AA的普通代码块。。。。。。。。。。。 
    AA的普通代码块。。。。。。。。。。。
    
  • 从上述代码可以看出来,静态代码块只执行了一次,那么引出问题:类什么时候被加载呢?


4.2.2、细节2---------类什么时候被加载呢?(重点!)
  1. 创建对象实例时(new)比如上述代码创建AA对象;

  2. 创建子类对象实例,父类也会被加载

    代码实例:

    public class text05 {
        public static void main(String[] args) {
            AA aa1 = new AA();
            AA aa2 = new AA();
        }
    }
    ​
    class BB{
        static{
            System.out.println("父类BB的静态代码块,,,,,,,,,,");
        };
        {
            System.out.println("父类BB的普通代码块。。。。。。。。。。。");
        };
    }
    ​
    class AA extends BB{
        static{
            System.out.println("子类AA的静态代码块,,,,,,,,,,");
        };
        {
            System.out.println("子类AA的普通代码块。。。。。。。。。。。");
        };
    }

    输出:

    父类BB的静态代码块,,,,,,,,,,
    子类AA的静态代码块,,,,,,,,,,
    父类BB的普通代码块。。。。。。。。。。。
    子类AA的普通代码块。。。。。。。。。。。
    父类BB的普通代码块。。。。。。。。。。。
    子类AA的普通代码块。。。。。。。。。。。
    类先加载,后实例化对象,先输出静态代码块。
  3. 使用类的静态成员时

    代码样例:

    public class text05 {
        public static void main(String[] args) {
    //        AA aa1 = new AA();
            System.out.println("------------");
            System.out.println(AA.num);
        }
    }
    ​
    class BB{
        static{
            System.out.println("父类BB的静态代码块,,,,,,,,,,");
        };
        {
            System.out.println("父类BB的普通代码块。。。。。。。。。。。");
        };
    }
    ​
    class AA extends BB{
        public static int num = 23;
        static{
            System.out.println("子类AA的静态代码块,,,,,,,,,,");
        };
        {
            System.out.println("子类AA的普通代码块。。。。。。。。。。。");
        };
    }

    输出:

    父类BB的静态代码块,,,,,,,,,, 
    子类AA的静态代码块,,,,,,,,,, 
    23
    
  • 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。

    如果只是使用类的静态成员时,普通代码块并不会执行。(如上述代码实例)


4.2.3、小结1
  1. static代码块是类加载时,执行,只会执行一次,因为类只加载一次。

  2. 普通代码块是在创建对象时调用的,创建一次,调用一次。可以理解为 普通代码块是对构造函数的补充

  3. 类加载的三种情况需要背下来!


4.2.4、细节3-----高频面试题---在一个类中代码块的调用顺序:(注意这里是在 一个类 的情况)
  1. 先调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,按照顺序执行

  2. 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,同样按照顺序执行

  3. 最后调用构造方法。

代码示例:

public class text06 {
    public static void main(String[] args) {
        DD dd = new DD();
    }
}
​
class DD{
​
    private int n2 = getVal2();
​
​
    static {
        System.out.println("dd的静态代码块方法。。。。。。");
    };
​
    {
        System.out.println("dd的普通代码块。。。。。。。");
    };
​
    private static int n1 = getVal();
​
    public static int getVal(){
        System.out.println("getVal()方法被调用");
        return 10;
    }
​
    public int getVal2(){
        System.out.println("getVal2()方法被调用");
        return 20;
    }
​
    public DD() {
        System.out.println("我是dd的无参构造方法。。。。。。。");
    }
}
​

输出:

dd的静态代码块方法。。。。。。 
getVal()方法被调用 
getVal2()方法被调用 
dd的普通代码块。。。。。。。 
我是dd的无参构造方法。。。。。。。
  • 个人理解:

    • 因为类是在创建对象之前先加载的,静态变量(也就是带static的)是随着类的加载而加载的,所以先执行静态成员

    • 然后创建对象,执行普通代码块 和 普通代码属性。

    • 构造方法是随着对象的创建,从而初始化的,所以最后执行。


4.2.5、细节4--构造器 super 和 普通代码块执行顺序

构造器的最前面其实隐含了 super()和 调用普通代码块,然而静态相关的代码块,属性初始化,在类加载时,就执行完毕,因此是优先于构造器 和 普通代码块执行的。

代码示例:

输出:

我是PP的static代码块。。。。。。。。
PP的构造函数。。。。。 
我是KK的普通代码块,,,,,, 
KK的构造函数。。。。。。。

4.2.6、细节6--------在创建一个子类的对象时(继承关系)执行顺序 *面试题!
  • 静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:

    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();//对象
    ​
            new C02();
        }
    }
    ​
    class C02 {
        private int n1 = m2();
        private static int n2 = 200;
    ​
        private void m1() {
            System.out.println("我是m1");
        }
        private static int m2() {
            System.out.println("我是m2");
            return 10;
        }
    ​
        static {
            //静态代码块,只能调用静态成员
            //System.out.println(n1);错误
            System.out.println(n2);//ok
            //m1();//错误
            m2();
        }
        {
            //普通代码块,可以使用任意成员
            System.out.println(n1);
            System.out.println(n2);//ok
            m1();
            m2();
        }
    }
    ​
    class A02 { //父类
        private static int n1 = getVal01();
        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 { //
    ​
        private static int n3 = getVal03();
    ​
        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)
            // TODO Auto-generated constructor stub
        }
    }

    抽出一个代码片段进行一个分析:

    class C02 {
        private int n1 = m2();
        private static int n2 = 200;
    ​
        private void m1() {
            System.out.println("我是m1");
        }
        private static int m2() {
            System.out.println("我是m2");
            return 10;
        }
    ​
        static {
            //静态代码块,只能调用静态成员
            //System.out.println(n1);错误
            System.out.println(n2);//ok
            //m1();//错误
            m2();
        }
        {
            //普通代码块,可以使用任意成员
            System.out.println(n1);
            System.out.println(n2);//ok
            m1();
            m2();
        }
    }

    这个代码片段,private int n1 = m2();这里是普通属性初始化调用静态方法。执行顺序:先执行静态代码块,再去执行private int n1 = m2();,然后依次按照规则执行。


以上 是我对代码块的学习记录~~欢迎小伙伴留言!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值