Java代码块(代码块与静态代码块使用细节及调用顺序)

本文详细介绍了Java中的代码块,包括静态代码块和普通代码块的加载时机和执行顺序。重点讨论了类加载的情况,如创建对象、继承关系下的执行顺序,并给出了实例演示。同时强调了静态代码块仅在类加载时执行一次,而普通代码块在每次创建对象时调用。
摘要由CSDN通过智能技术生成

目录

1、代码块的基本介绍

2、静态代码块

类什么时候加载【重点】 

创建对象实例时(new)

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

使用类的静态成员时(静态属性,静态方法)

3、代码块的使用小细节

普通的代码块,在创建对象实例时,会被隐式的调用。每被创建一次,就会调用一次。

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

4、创建一个对象时,在一个类中的调用顺序

5、存在继承关系时,类中的调用顺序

6、静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员


1、代码块的基本介绍

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

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

相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作。

场景:如果多个构造器中都有重复的语句,可以将重复部分抽取到代码块中,提高代码的重用性。

例如:  看电影时,我们要打开荧幕,再播放广告,等时间到了在播放正片,每播放新的一部影片时,我们都要重复打开荧幕和播放广告这个动作,我们就可以提出来放在代码块中,这样每次创建对象时,就会优先执行代码块中的内容。

public class CodeBook {
    public static void main(String[] args) {
        Movie movie = new Movie("银河补习班");
        System.out.println("=============");
        Movie movie1 = new Movie("人生大事");
    }
}

class Movie{
    private String name;

    {
        System.out.println("电影荧幕打开");
        System.out.println("播放广告");
    }

    public Movie(String name) {
        this.name = name;
        System.out.println("电影"+name+"正在播放");
    }
}

   运行结果

2、静态代码块

static代码块叫静态代码块,作用是对类进行初始化它随着类的加载进行初始化,而且随着类的加载而被执行并且只会执行一次

如果是普通代码块,每次创建一个对象就执行一次。

类什么时候加载【重点】 

  1. 创建对象实例时(new)

    public class TestC {
        public static void main(String[] args) {
            //1、创建对象实例时(new)
            new AAA();
        }
    }
    
    class AAA{
        static{
            System.out.println("AAA的静态代码块被调用");
        }
    }

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

    public class TestC {
        public static void main(String[] args) {
            //2、创建子类对象实例时,父类也会被加载,而且父类先被加载,子类后被加载
            new BBB();
          }
    }
    
    class BBB extends AAA{
        static{
            System.out.println("BBB的静态代码块被调用");
        }
    }
    
    class AAA{
        static{
            System.out.println("AAA的静态代码块被调用");
        }
    }

     创建子类对象实例时,父类也会被创建,而且父类先被加载,子类后被加载。

  3. 使用类的静态成员时(静态属性,静态方法)

    public class TestC {
        public static void main(String[] args) {
            //3、使用类的静态成员时(静态属性,静态方法)
            System.out.println(CCC.n);
          }
    }
    
    class CCC{
        public static int n=99;
    
        static{
            System.out.println("CCC的静态代码块被调用");
        }
    }

3、代码块的使用小细节

普通的代码块,在创建对象实例时,会被隐式的调用。每被创建一次,就会调用一次。

public class TestC {
    public static void main(String[] args) {
        DDD ddd = new DDD();
        DDD ddd1 = new DDD();
        DDD ddd2 = new DDD();
      }
}

class DDD{
    static{
        System.out.println("DDD的静态代码块被调用");
    }
    {
        System.out.println("DDD的普通代码块被调用");
    }
}

静态代码块只在类加载时创建且只创建一次,而普通代码块每创建一次对象就调用一次。 

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


public class TestC {
    public static void main(String[] args) {
        System.out.println(DDD.n2);
      }
}

class DDD{
    public static int n2=88;//静态属性
    static{//静态代码块
        System.out.println("DDD的静态代码块被调用");
    }
    {//普通代码块
        System.out.println("DDD的普通代码块被调用");
    }
}

直接调用类的静态属性,导致类加载,静态代码块被调用。

只加载类,未创建对象,普通代码块不会被调用。 

1、static代码块时类加载时执行,只会执行一次

2、普通代码块是在创建对象时调用的,创建一次,调用一次

4、创建一个对象时,在一个类中的调用顺序

  1. 静态代码块和静态属性的初始化(注意:静态代码块和静态属性初始化调用的优先级相同,如有多个静态代码块和静态属性,按定义的顺序调用
  2. 调用普通代码块和普通属性,优先级和静态代码块一样(同上)
  3. 调用构造方法。
    public class TestD {
        public static void main(String[] args) {
        D d=new D();
        }
    }
    
    class D{
        public D() {
            System.out.println("D的无参构造器被调用");
        }
        {
            System.out.println("普通代码块被调用");
        }
        private int n2 = getn2();
        private static int n1=getn1();
        static{
            System.out.println("D的静态代码块被调用");
        }
        public static int getn1(){
            System.out.println("getn1被调用");
            return 100;
        }
        public int getn2(){
            System.out.println("getn2被调用");
            return 99;
        }
    }

    大家可以先思考下上方的代码的输出顺序为什么。

        

5、存在继承关系时,类中的调用顺序

  1. 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
  2. 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
  3. 父类的普通代码块和普通属性的初始化(优先级一样,按定义顺序执行)
  4. 父类的构造方法
  5. 子类的普通代码块和普通属性的初始化(优先级一样,按定义顺序执行)
  6. 子类的构造方法
    public class TestD {
        public static void main(String[] args) {
        D d=new D();
        }
    }
    
    class D extends E{
        public D() {
            System.out.println("子类D的无参构造器被调用");
        }
        {
            System.out.println("子类D的普通代码块被调用");
        }
        private int n2 = getn2();
        private static int n1=getn1();
        static{
            System.out.println("子类D的静态代码块被调用");
        }
        public static int getn1(){
            System.out.println("子类getn1被调用");
            return 100;
        }
        public int getn2(){
            System.out.println("子类getn2被调用");
            return 99;
        }
    }
    class E{
        public E() {
            System.out.println("父类E的无参构造器被调用");
        }
        {
            System.out.println("父类E的普通代码块被调用");
        }
        private int n2 = getn4();
        private static int n1=getn3();
        static{
            System.out.println("父类E的静态代码块被调用");
        }
        public static int getn3(){
            System.out.println("父类的getn3被调用");
            return 100;
        }
        public int getn4(){
            System.out.println("父类的getn4被调用");
            return 99;
        }
    }

6、静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员

class F{
    private int n1=66;
    private static int n2 = 55;
    private void m1(){

    }
    private static void m2(){

    }

    static {
        //静态代码块只能调用静态成员
        //System.out.println(n1);//直接报错
        System.out.println(n2);//ok
        //m1();//报错,提示不能调用非静态方法
        m2();//ok
    }
    {//普通代码块可以调用任何成员
        System.out.println(n1);
        System.out.println(n2);
        m1();
        m2();
    }
}

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值