类的初始化变量和方法的执行顺序(父子类)

2019-08-09 00:00:00 变量 初始化 父子

static和没有static的区别
*static的属性/方法在类加载时就已经做好准备,因此类名.就可以调用,与对象存在不存在无关。
*非static的属性/方法隶属于对象,必须先创建对象,才能使用。
  static的方法中,不能使用非静态的属性或者方法,必须先创建对象,然后用对象.调用;而非static的方法中,可以直接使用静态的属性或方法。
只有隶属于类(所有对象共享)的属性才能加static,static不能随便加。

代码块 — java允许直接用{}写代码,叫代码块。
*写在类体中的代码块叫构造块,每创建一个对象,构造块都会被执行一次。
*前面加static的构造块叫静态代码块,类加载时执行一次。

对象创建的过程
 a.单个对象创建的执行过程
(1)main()方法是程序的入口,使用new关键字创建对象时会在堆区申请内存空间;
(2)若成员变量没有指定初始值,则采用默认初始化方式处理;
(3)若成员变量进行显式初始化,则采用指定的初始值进行处理;
(4)执行构造块中的代码,可以对成员变量进行赋值操作;
(5)执行构造方法体中的代码,可以对成员变量进行再次赋值;
(6)此时对象创建完毕,继续向下执行;

b.子类对象创建的执行过程
(1)main()方法是程序的入口,使用new关键字创建对象时会在堆区申请内存空间;
(2)先加载父类再加载子类,因此先执行父类的静态代码块再执行子类的静态代码块;
(3)执行父类的构造块和父类的构造方法体,此时内部的父类对象构造完毕;
(4)执行子类的构造块和子类的构造方法体,此时子类对象构造完毕;
(5)构造完毕后继续向下执行;

执行顺序:(静态代码块和静态变量谁在前面就先执行谁)

父类静态代变量、
父类静态代码块、
子类静态变量、
子类静态代码块、
父类非静态变量(父类实例成员变量)、
父类构造函数、
子类非静态变量(子类实例成员变量)、
子类构造函数。

 

代码示例

package com.jdk.learn;

public class ClassLoaderTest {

  public static void main(String[] args) {
    son sons=new son();
  }
}

class parent{
  private static int a=1;
  private static int b;
  private int c=initc();
  static {
    b=1;
    System.out.println("1.父类静态代码块:赋值b成功");
    System.out.println("1.父类静态代码块:a的值"+a);
  }
  int initc(){
    System.out.println("3.父类成员变量赋值:---> c的值"+c);
    this.c=12;
    System.out.println("3.父类成员变量赋值:---> c的值"+c);
    return c;
  }
  public parent(){
    System.out.println("4.父类构造方式开始执行---> a:"+a+",b:"+b);
    System.out.println("4.父类构造方式开始执行---> c:"+c);
   }
}

class son extends parent{
  private static int sa=1;
  private static int sb;
  private int sc=initc2();
  static {
    sb=1;
    System.out.println("2.子类静态代码块:赋值sb成功");
    System.out.println("2.子类静态代码块:sa的值"+sa);
  }
  int initc2(){
    System.out.println("5.子类成员变量赋值--->:sc的值"+sc);
    this.sc=12;
    return sc;
  }
  public son(){
    System.out.println("6.子类构造方式开始执行---> sa:"+sa+",sb:"+sb);
    System.out.println("6.子类构造方式开始执行---> sc:"+sc);
  }
}

 

执行结果:

1.父类静态代码块:赋值b成功
1.父类静态代码块:a的值1
2.子类静态代码块:赋值sb成功
2.子类静态代码块:sa的值1
3.父类成员变量赋值:---> c的值0
3.父类成员变量赋值:---> c的值12
4.父类构造方式开始执行---> a:1,b:1
4.父类构造方式开始执行---> c:12
5.子类成员变量赋值--->:sc的值0
6.子类构造方式开始执行---> sa:1,sb:1
6.子类构造方式开始执行---> sc:12

 

总结:

当我们进行new实例化进行操作的时候,JVM都进行了什么操作呢?
如果你看过深入理解jvm的话,应该会比较清楚,当我们使用new关键字进行实例化的时候,会进行如下几步处理:

加载
此阶段加载类的字节码信息到内存
连接
此阶段进行验证,分配默认值,符号引用转直接引用
初始化
为成员进行赋值等

使用
对实例进行操作比如sons.toString()

对于我们的实例而言,我们只关注连接和初始化阶段即可。
连接阶段我们按照类结构(成员变量(先),方法(后)等)的顺序(不是书写顺序),先对变量进行赋默认值0,对象的话为null。

初始化的时候,就是对对象进行赋值,比如c执行initc()进行赋值。

 

参考博客:https://blog.csdn.net/u014042066/article/details/77574956

相关文章