Java代码块

免责声明:java基础资料均来自于韩顺平老师的《循序渐进学Java零基础》教案,具体视频内容可以去B站观看,这些资料仅用于学习交流,不得转载用于商业活动

Java代码块

1.1 基本介绍

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

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

1.2 基本语法

[修饰符]{

  代码

};

说明注意:

  1. 修饰符可选,要写的话,也只能写static
  2. 代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块/非静态代码块
  3. 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)
  4. ;可以写上,也可以省略
  5. 代码块相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作
  6. 场景:如果多个构造器中都有重复的语句,可以抽取到初始化代码块中,提高代码的重用性
 1 public class CodeBlock {
 2     public static void main(String[] args){
 3         Movie movie = new Movie("你好,李焕英");
 4         System.out.println("========");
 5         Movie movie2 = new Movie("流浪地球2",89.5,"吴京");
 6         
 7     }
 8 }
 9 
10 class Movie{
11     private String name;
12     private double price;
13     private String diretor;
14 
15     //3个构造器-》重载
16     //(1)下面的三个构造器都有相同的语句
17     //(2)这样代码看起来比较冗余
18     //(3)这时我们可以把相同的语句,放入到一个代码块中,即可
19     //(4)这样当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
20     //(5)代码块调用的顺序优先于构造器
21     {
22         System.out.println("电影屏幕打开...");
23         System.out.println("广告开始...");
24         System.out.println("电影正式开始...");
25     }
26 
27     public Movie(String name){
28         System.out.println("Movie(String name)被调用");
29         this.name = name;
30     }
31 
32     public Movie(String name,double price){
33         this.name = name;
34         this.price = price;
35     }
36 
37     public Movie(String name,double price,String diretor){
38         System.out.println("Movie(String name,double price,String diretor)被调用...");
39         this.name = name;
40         this.price = price;
41         this.diretor = diretor;
42     }
43 }

1.3 代码块使用注意事项和细节讨论

  • static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而运行,并且只会执行一次,如果是普通代码块,每创建一个对象,就执行
  • 类什么时候被加载
    • 创建对象实例时(new)
    • 创建子类对象实例,父类也会被加载
    • 使用类的静态成员时(静态属性,静态方法)
  • 普通的代码块,在创建对象实例时,会被隐式的调用
    • 被创建一次,就会调用一次
    • 如果只是使用类的静态成员时,普通代码块并不会执行

小结:

  1. static代码块是类加载时,执行,只执行一次
  2. 普通代码块是在创建对象时调用的,创建一次,调用一次
  3. 类加载的3中情况,需要记住
public class CodeBlockDetail {
    public static void main(String[] args) {
        //类被加载的情况举例
        //1.创建对象实例时(new)
        //AA aa = new AA();
        //2.创建子类对象实例,父类也会被加载,而且,父类先被加载,子类后被加载
        AA aa2 = new AA();
        //3.使用类的静态成员时(静态属性,静态方法)
        System.out.println(Cat.n1);
        //static 代码块,是在类加载是,执行的,而且只会执行一次
        DD dd = new DD();
        DD dd1 =new DD();
        //普通的代码块,在创建对象实例时,会被隐式的调用
        //被创建一次,就会调用一次
        //如果只是使用类的静态成员时,普通代码块并不会执行
        System.out.println(DD.n1);//8888 静态模块一定会执行
    }
}

class DD{
    public static int n1 = 8888;//静态属性
    //静态代码块
    static{
        System.out.println("DD的静态代码块1被执行...");
    }
    //普通代码块,在new对象时,被调用,而且是每创建一个对象,就调用一次
    //可以这样简单的理解 普通代码块是构造器的补充
    {
        System.out.println("DD的普通代码块");
    }
}

class Animal{
    //静态代码块
    static{
        System.out.println("Animal的静态代码1被执行...");
    }
}

class Cat extends Animal{
    public static int n1 = 999;//静态属性
    //静态代码块
    static{
        System.out.println("Cat的静态代码1被执行...");
    }
}

class BB{
    //静态代码块
    static{
        System.out.println("BB的静态代码1被执行");
    }
}

class AA extends BB{
    //静态代码块
    static {
        System.out.println("AA的静态代码1被执行...");
    }
}

创建一个对象时,在已给类调用顺序是:(重点,难点)

  1. 调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)
  2. 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)
  3. 调用构造方法
 1 public class CodeBlockDetail02 {
 2     public static void main(String[] args) {
 3         /*
 4         A类的调用顺序:
 5         1.A静态代码块01
 6         2.getN1被调用
 7         3.A普通代码块01
 8         4.A()构造器被调用
 9         5.getN2被调用...
10          */
11         A a = new A();
12         a.getN2();
13     }
14 }
15 
16 class A{
17     //普通代码块
18     {
19         System.out.println("A的普通代码块01");
20     }
21     //静态代码块
22     static{
23         System.out.println("A静态代码块01");
24     }
25     //静态属性的初始化
26     private static int n1=getN1();
27     public static int getN1(){
28         System.out.println("getN1被调用...");
29         return 100;
30     }
31     //普通方法/非静态方法
32     public int getN2(){
33         System.out.println("getN2被调用...");
34         return 200;
35     }
36     //无参构造器
37     public A(){
38         System.out.println("A()构造器被调用");
39     }
40 }

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

 1 public class CodeBolckDetail03 {
 2     public static void main(String[] args) {
 3         /*
 4         * (1)AAA的普通代码块
 5         * (2)AAA()构造器被调用
 6         * (3)BBB的普通代码块
 7         * (4)BBB()构造器被调用
 8         * */
 9         new BBB();
10     }
11 }
12 
13 class AAA{//父类Object
14     {
15         System.out.println("AAA的普通代码块");
16     }
17     public AAA(){
18         //(1)super();
19         //(2)调用本类的普通代码块
20         System.out.println("AAA()构造器被调用...");
21     }
22 }
23 
24 class BBB extends AAA{
25     {
26         System.out.println("BBB的普通代码块...");
27     }
28     public BBB(){
29         //(1)super();
30         //(2)调用本类的普通代码块
31         System.out.println("BBB()构造器被调用...");
32     }
33 }

我们看一下创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:

  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();//对象
    }
}

class A02{//父类
    private static int n1 = getVal01();
    static{
        System.out.println("A02的一个静态代码块...");
    }
    {
        System.out.println("A02的一个普通代码块..");
    }
    public int n3=getVal02();//普通属性初始化
    public static int getVal01(){
        System.out.println("getVal01");
        return 10;
    }
    public int getVal02(){
        System.out.println("getVal02");
        return 10;
    }

    public A02(){
        //隐藏
        //super();
        //普通代码块和普通属性的初始化
        System.out.println("A02的构造器");
    }
}

class C02{
    private int n1 = 100;
    private static int n2 = 200;
    private void m1(){

    }
    private static void m2(){

    }
    static {
        //静态代码块,只能调用静态成员
        //System.out.println(n1);//错误
        System.out.println(n2);
        //m1();//错误
        m2();
    }
    {
        //普通代码块,可以使用任意成员
        System.out.println(n1);
        System.out.println(n2);//ok
        m1();
        m2();
    }
}

class B02 extends A02{
    private static int n3 =getVal03();
    static{
        System.out.println("B02的一个静态代码块..");
    }
    public int n5=getVal04();
    {
        System.out.println("B02的第一个普通代码块..");
    }
    public static int getVal03(){
        System.out.println("getVal03");
        return 10;
    }
    public int getVal04(){
        System.out.println("getVal04");
        return 20;
    }

    public B02(){//构造器
        //隐藏了
        //super()
        //普通代码块和普通属性的初始化...
        System.out.println("B02的构造器");
    }
}

 

posted @ 2024-07-09 11:54  万溪汇海  阅读(6)  评论(0编辑  收藏  举报