java静态代码块,构造方法,初始化块的执行顺序

时间:2022-04-10 19:31:48

代码Parent和Sub进行讲解

public class Parent {
    
    private static final String name;
    
    public Parent() {
        System.out.println("父类构造方法");
    }
    static{
        name="hello parent";
        System.out.println("父类静态块1");
    }
    static{
        System.out.println("父类静态块2");
    }
    {
        System.out.println("父类非静态块1");
    }
    {
        System.out.println("父类非静态块2");
    }
    
}
public class Sub extends Parent{
    
    public Sub() {
        System.out.println("子类构造方法");
    }
    static{
        System.out.println("子类静态块");
    }
    
    {
        System.out.println("子类非静态块");
    }
    
}
public class Test {
    
    public static void main(String[] args) {
        Parent s1=new Sub();
        Parent s2=new Sub();
    }

}
运行结果:

父类静态块1
父类静态块2
子类静态块

父类非静态块1
父类非静态块2
父类构造方法
子类非静态块
子类构造方法

父类非静态块1
父类非静态块2
父类构造方法
子类非静态块
子类构造方法

结果:

  父类静态代码块

  子类静态代码块

    ----- 类加载时只调用一次


  父类代码块

  父类构造方法

  子类代码块

  子类构造方法

    -----每次创建一个对象就调用一次

 

结论:

  static修饰的代码块属于静态代码块属于类,加载时只调用一次;

  非static修饰的代码块属于对象,每次创建对象都会运行非static修饰的代码块。

  因为静态代码优先于非静态的代码,被static修饰的成员都是类成员,会随着JVM加载类的时候加载而执行,

  没有被static修饰的成员也被称为实例成员,需要创建对象才会随之加载到堆内存,所以静态的会优先非静态的先执行

 

以上主要讲解的是代码块的执行顺序,读者可能不易理解的final和static的使用,以下是对final的static的简单总结,辅助读者理解

static:

  被static修饰的方法和属性独立于该类的任何对象  不需要创建对象就可以进行访问

  使用static修饰的方法和属性可以直接通过类进行调用

  static修饰代码块,类加载时候就会执行

  static修饰的变量 :内存中只有一份,不需要创建对象就可以进行调用,只要属于这个类创建的对象,都会共享这个变量

      成员变量 : 只有在对象创建之后才能被调用,每一个对象都会拷贝一份,每个对象只能访问自己的成员变量

  static修饰方法:又称静态方法,属于类,不需要创建对象就可以调用。静态方法不能调用非静态方法,内部不能使用this、super

  static可以直接创建代码块

  例如:

static {
    
             //自己的逻辑   
    }

  static修饰的静态代码块在一个类中可以有多个,加载的顺序按照书写的顺序。虚拟机只会在加载类的时候对代码块加载一次

 

final:

  final 修饰类 :类不能被继承、final修饰的类中的方法,默认全是final修饰的

  父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的

  final修饰方法 : 使用final修饰的方法,子类是不能进行重写的

  final修饰的变量,一旦给了值之后,是不能被修改的

    注意:final变量定义的时候,可以先声明,而不给初值

       这种变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化

    例如:

      

 public  class HelloWord{       

    private  final int E;    

    public HelloWorld(){
            
        E=10;              //这样也是可以的,不会报编译错误,而且运行也正常
    }

    //后期使用,E=10如果被修改会报错

 }