静态代码块、匿名代码块、构造器
静态代码块、匿名代码块、构造器区别和联系、执行先后顺序
- 静态代码块(
staticblock):- 静态代码块在类加载时执行,且只执行一次。
- 它是在 JVM 加载类时执行的,在任何对象创建之前。
- 如果类没有被加载,静态代码块不会被执行。
- 匿名代码块(实例初始化块):
- 匿名代码块属于实例初始化块(
instance initializer block),在每次创建对象时执行。 - 它会在构造器之前执行,但每次创建对象时都会执行。
- 匿名代码块属于实例初始化块(
- 构造器(Constructor):
- 构造器是在创建对象时执行的,它用于初始化对象。
- 在匿名代码块执行完后,构造器会被调用。
执行顺序示意图
- 静态代码块 → 匿名代码块 → 构造器
具体的执行过程是: 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 修饰了 不能再被继承

静态方法、非静态方法的调用
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
}
}

浙公网安备 33010602011771号