静态代码块、匿名代码块、构造器

静态代码块、匿名代码块、构造器区别和联系、执行先后顺序

  1. 静态代码块static block):
    • 静态代码块在类加载时执行,且只执行一次。
    • 它是在 JVM 加载类时执行的,在任何对象创建之前。
    • 如果类没有被加载,静态代码块不会被执行。
  2. 匿名代码块(实例初始化块):
    • 匿名代码块属于实例初始化块(instance initializer block),在每次创建对象时执行。
    • 它会在构造器之前执行,但每次创建对象时都会执行。
  3. 构造器(Constructor):
    • 构造器是在创建对象时执行的,它用于初始化对象。
    • 在匿名代码块执行完后,构造器会被调用。

执行顺序示意图

  • 静态代码块匿名代码块构造器

具体的执行过程是: 1 静态代码块:类加载时执行一次。 2 匿名代码块:每次实例化对象时执行。 3 构造器:每次实例化对象时执行,且最后执行。

区别

  1. 静态代码块
    • 作用:用于类级别的初始化,只在类加载时执行一次。
    • 触发时机:类加载时。
    • 访问对象实例:不能访问实例成员(成员变量、成员方法),只能访问静态成员。
  2. 匿名代码块
    • 作用:用于每个对象的实例化时执行,用来初始化实例。
    • 触发时机:每次创建对象时执行。
    • 访问对象实例:可以访问实例成员。
  3. 构造器
    • 作用:用于初始化对象,完成实例的创建过程。
    • 触发时机:每次创建对象时执行。
    • 访问对象实例:可以访问实例成员。

联系

  • 匿名代码块和构造器都是与对象实例化过程相关的,它们都会在对象创建时执行,但匿名代码块先于构造器执行。
  • 静态代码块与对象实例化无关,它是类加载时执行的,与对象的创建和构造器无关。

总结

  • 静态代码块先于实例相关的代码执行,并且仅执行一次(类加载时)。
  • 匿名代码块每次实例化对象时执行,并且会在构造器之前执行。
  • 构造器用于完成对象的初始化,在匿名代码块之后执行。
package com.oop.demo08;
//主要讨论 匿名代码块、静态代码块、构造器区别和联系,以及先后顺序
//静态代码块 → 匿名代码块 → 构造器
//具体的执行过程是: 1 静态代码块:类加载时执行一次。 2 匿名代码块:每次实例化对象时执行。 3 构造器:每次实例化对象时执行,且最后执行。
public class Person /*extends Animal*/{ //Animal1类被final 修饰了 不能再被继承
    //2. 匿名代码块,属于实例初始化块 在每次创建对象时执行。它会在构造器之前执行,但每次创建对象时都会执行
    //一般用来设置初始条件
    {
        System.out.println("匿名构造器执行了!");
    }
    //1. 静态代码块  类加载就执行 ,在任何对象创建之前,若类没有被加载,就不执行。且执行也就执行一次
    static {
        System.out.println("静态代码块执行了!");
    }
    //3. 构造器
    //构造器是在创建对象时执行的,它用于初始化对象。在匿名代码块执行完后,构造器会被调用。
    public Person() {
        System.out.println("构造器执行了!");
    }

    public static void main(String[] args) {
        Person p = new Person();
        System.out.println("=================");
        Person p1 = new Person();
        System.out.println("=================");
        Person p2 = new Person();
    }

}

输出结果:

静态代码块执行了!
匿名构造器执行了!
构造器执行了!
=================
匿名构造器执行了!
构造器执行了!
=================
匿名构造器执行了!
构造器执行了!

复习类变量(静态变量)、实例变量

package com.oop.demo08;

/**
 * 复习static 静态属性(类变量)、静态方法、静态代码块
 * 静态属性(类变量)类公有,可以通过类赋值查值,一改都改,实例变量只能通过实例访问赋值,局部变量只在代码块里存在
 *
 * 静态方法可以调用静态方法,不能直接调用非静态方法。非静态方法可以调用静态方法,调用实例化后的非静态方法
 * 静态导入包
 * final 定义的后类 不能再作父类
 * */
public class Student {
    public static int numInt=10_000; //类变量 静态变量
    public  float numFloat=5_000.0f; //实例变量

    public static void main(String[] args) {
        System.out.println("==============类变量的访问:1.直接访问 2.通过类名访问  3.通过创建实例访问==============");
        System.out.println(numInt);//直接访问类变量
        System.out.println(Student.numInt);//通过类名访问类变量
        Student s1 = new Student();
        System.out.println(s1.numInt);//通过实例访问类变量
        System.out.println("==============实例变量的访问和修改:1.创建实例 2.通过实例访问和修改实例变量 3.实例变量互不影响");
        System.out.println(s1.numFloat);//实例变量要通过实例访问、赋值
        Student s2 = new Student();//实例变量基于实例,彼此之间个不干扰
        s2.numFloat=5_001.0f;//s2 修改实例变量不影响s1 的实例变量
        System.out.println(s1.numFloat);//s2 的实例变量 numfloat 不影响s1实例变量 的 numfloat
        //但是s1 s2对列变量的修改是同步的
        System.out.println("==============类变量的修改:1.直接修改 2.通过类名修改 3.通过实例修改  4.一改都改");
        numInt = 10_001;//直接修改类变量   公用的 一改都改!
        System.out.println(numInt);
        Student.numInt = 10_002;//通过类名修改类变量
        System.out.println(Student.numInt);
        s1.numInt = 10_003;//通过实例修改类变量
        System.out.println(s1.numInt);
        System.out.println("==============");
    }
}

输出结果:

==============类变量的访问:1.直接访问 2.通过类名访问  3.通过创建实例访问==============
10000
10000
10000
==============实例变量的访问和修改:1.创建实例 2.通过实例访问和修改实例变量 3.实例变量互不影响
5000.0
5000.0
==============类变量的修改:1.直接修改 2.通过类名修改 3.通过实例修改  4.一改都改
10001
10002
10003
==============

final 修饰的类不能再被继承

package com.oop.demo08;
//测试 类用final修饰后 不能再作为父类了(断子绝孙) 不能再被Person类继承
final public class Animal {
}
public class Person /*extends Animal*/{ //Animal1类被final 修饰了 不能再被继承

image-20250113104538555

静态方法、非静态方法的调用

package com.oop.demo08;
//讨论静态方法对静态方法的调用  非静态可以调用静态方法  调用非静态方法需要先实例化后再使用
//方法的定义 修饰符(公共还是非公共  静态还是非静态 返回值类型 方法名(形式参数){方法体})
public class Teacher {
    //定义静态方法
    public static void run(){

    }
    //定义非静态方法
    public void go(){
        run();//非静态方法可以调用静态方法
        Teacher.run();//
    }

    public static void main(String[] args) {
        //静态方法里面调用静态方法
        run();//静态方法直接调用
        Teacher.run();//通过类名直接调用
        //go();//直接调用非静态方法出错
        //非静态方法的调用
        new Teacher().go();//创建实例后调用
        Teacher t1 = new Teacher();
        t1.go();//21行 22行效果同20行 但是创建了具体实例t1
    }
}
posted @ 2025-01-13 13:59  panghuhu~  阅读(120)  评论(0)    收藏  举报