深入理解类与实例的初始化过程

1.类的初始化过程

  • 一个类要创建实例需要先加载并初始化该类
    -- main方法所在的类需要先加载和初始化
  • 一个子类要初始化需要先初始化父类
  • 一个类的初始化就是执行<clinit>()方法
    -- <clinit>()方法是自动生成的在字节码中可以找到,是由静态类变量显示赋值代码和静态代码块组成,这两个是谁在上面先执行谁,并且只执行一次

2.实例的初始化过程

  • 实例的初始化就是执行<init>()方法
    -- <init>() 方法可能有多个重载,有几个构造方法就有几个<init>()
    -- <init>() 方法包括非静态类实例变量显示赋值代码,非静态代码块和对应构造器代码组成,前两个是谁在上面先执行谁,构造器代码最后执行
    -- 每次创建实例都要调用对应的<init>()方法,有因为子类的构造器的首行是super();所以每次都会调用父类的<init>()方法

3.方法的重写

  • 那些方法不能被重写
    -- final方法
    -- 静态方法
    -- private等子类中不可见的方法
  • 对象的多态性
    -- 子类重写了父类的方法,通过子类对象调用这个方法一定是调调用子类的方法
    -- 非静态的方法默认的调用对象是this
    -- this对象在构造器中就是正在创建的对象

4.代码实例

package clinit;

public class Father {

    private int i = test();
    private static int j = method();

    static {
        System.out.println("(1)");
    }

    Father () {
        System.out.println("(2)");
    }

    {
        System.out.println("(3)");
    }

    public int test () {
        System.out.println("(4)");
        return 1;
    }

    public static int method () {
        System.out.println("(5)");
        return 1;
    }



}

package clinit;

/**
 * son 1
 */
public class son extends Father{

    private int i = test();
    private static int j = method();

    static {
        System.out.println("(6)");
    }

    son() {
        System.out.println("(7)");
    }

    {
        System.out.println("(8)");
    }

    public int test () {
        System.out.println("(9)");
        return 1;
    }

    public static int method () {
        System.out.println("(10)");
        return 1;
    }

    public static void main(String[] args) {
        /**
         * 这里的执行结果为 (5) (1) (10) (6)
         * 解析 : main方法所在的类会自动加载类和类的初始化
         * 就是执行<clinit>()
         * 因为要对子类进行类的初始化 先执行父类的初始化
         * 因为private static int j = method();在前先执行 (5)
         * 之后执行静态代码块 (1)
         * static {
         *         System.out.println("(1)");
         *     }
         *
         * 加载子类 亦然  (10) (6)
         *
         */
    }

}

package clinit;

/**
 * son 2
 */
public class Son2 extends Father{

    private int i = test();
    private static int j = method();

    static {
        System.out.println("(6)");
    }

    Son2() {
        System.out.println("(7)");
    }

    {
        System.out.println("(8)");
    }

    public int test () {
        System.out.println("(9)");
        return 1;
    }

    public static int method () {
        System.out.println("(10)");
        return 1;
    }

    public static void main(String[] args) {
        /**
         * 这里的执行结果为 (5) (1) (10) (6)
         * 解析 : main方法所在的类会自动加载类和类的初始化
         * 就是执行<clinit>()
         * 因为要对子类进行类的初始化 先执行父类的初始化
         * 因为private static int j = method();在前先执行 (5)
         * 在执行静态代码块 (1)
         * static {
         *         System.out.println("(1)");
         *     }
         *
         * 加载子类 亦然  (10) (6)
         *
         *
         * 类的初始话加载完了之后就是  实例的初始话  (9) (3) (2)
         * 构造器的第一句就是super  所以先执行父类的<init>()
         * private int i = test(); 他在前  执行父类的这一句  但是在父类的<init>()方法中test是有this对象调用的
         *this对象又指正在创建的对象所以这里就调用的是子类的test  这里是(9)[类的初始化没有出现这种情况的原因是static的方法没有办法重写]
         *{
         *         System.out.println("(3)");  (3)
         *     }
         * 构造器最后执行  (2)
         * Father () {
         *         System.out.println("(2)");
         *     }
         *
         * 子类亦然  (9) (8) (7)
         *  new Son2() 就把实例话的过程在走一遍  9 3 2 9 8 7
         */
        Son2 s1 = new Son2();
        System.out.println();
        Son2 s2 = new Son2();
    }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容