• java 类加载及实例化的调用顺序


    1.没有继承的情况

    单独一个类的场景下,初始化顺序为依次为 静态变量和静态代码块(看两者的书写顺序),继承的基类的构造函数,成员变量,被调用的构造函数。

    代码呈现:

    public class Test {
    	public static void main(String[] args) {
    		Son son = new Son();
    	}
    }
    
    class Son {
    	public Son() {
    		System.out.println("this is son.");
    	}
    
    	public Son(int age) {
    		System.out.println("son is " + age + " years old.");
    	}
    
    	private Height height = new Height(1.8f);
    
    	static {
    		System.out.println("this is static code");
    	}
    	
    	public static Gender gender = new Gender(true);
    }
    
    class Height {
    	public Height(float height) {
    		System.out.println("initializing height " + height + " meters.");
    	}
    }
    
    class Gender {
    	public Gender(boolean isMale) {
    		if (isMale) {
    			System.out.println("this is a male.");
    		} else {
    			System.out.println("this is a female.");
    		}
    	}
    }
    
    this is static code
    this is a male.
    initializing height 1.8 meters.
    this is son.
    

    2.继承的情况

    稍微修改一下代码,添加两个基类,让Son继承Father, Father继承Grandpa。
    继承的情况就比较复杂了。由于继承了基类,还将往上回溯,递归地调用基类的无参构造方法。
    在我们的例子中,在初始化静态数据后,会先往上追溯,调用Father的默认构造方法,此时再往上追溯到Grandpa的默认构造方法。

    注:如果在子类的构造方法中,显式地调用了父类的带参构造方法,那么JVM将调用指定的构造方法而非默认构造方法。

    基类和子类均有静态数据,成员变量和构造方法的场景

    我们继续修改代码,让其最终呈现如下:

    public class Test {
    	public static void main(String[] args) {
    		Son son = new Son();
    	}
    }
    
    class Grandpa {
        public Grandpa() {
            System.out.println("this is grandpa.");
        }
    
        public Grandpa(int age) {
            System.out.println("grandpa is " + age + " years old.");
        }
    
        private Height height = new Height(1.5f);
    
        public static Gender gender = new Gender(true, "grandpa");
        
        static {
    		System.out.println("this is static code");
    	}
    }
    
    class Father extends Grandpa {
    
        public Father() {
            System.out.println("this is father.");
        }
    
        public Father(int age) {
            System.out.println("father is " + age + " years old.");
        }
    
        private Height height = new Height(1.6f);
    
        public static Gender gender = new Gender(true, "father");
    }
    
    class Son extends Father {
    
        public Son() {
            super(50);
            System.out.println("this is son.");
        }
    
        public Son(int age) {
            System.out.println("son is " + age + " years old.");
        }
    
        private Height height = new Height(1.8f);
    
        public static Gender gender = new Gender(true, "son");
    }
    
    class Height {
        public Height(float height) {
            System.out.println("initializing height " + height + " meters.");
        }
    }
    
    class Gender {
        public Gender(boolean isMale) {
            if (isMale) {
                System.out.println("this is a male.");
            } else {
                System.out.println("this is a female.");
            }
        }
    
        public Gender(boolean isMale, String identify) {
            if (isMale) {
                System.out.println(identify + " is a male.");
            } else {
                System.out.println(identify + " is a female.");
            }
        }
    }
    
    grandpa is a male.
    this is static code
    father is a male.
    son is a male.
    initializing height 1.5 meters.
    this is grandpa.
    initializing height 1.6 meters.
    father is 50 years old.
    initializing height 1.8 meters.
    this is son.
    

    在我们的示例中,加载顺序应该是这样的:

    Grandpa 静态数据
    Father 静态数据
    Son 静态数据
    Grandpa 成员变量
    Grandpa 构造方法
    Father 成员变量
    Father 构造方法
    Son 成员变量
    Son 构造方法
    

    一般来说,顺序如下:

    1.首先是父类的静态变量和静态代码块(看两者的书写顺序);
    2.第二执行子类的静态变量和静态代码块(看两者的书写顺序);
    3.第三执行父类的成员变量赋值
    4.第四执行父类类的构造代码块
    5.第五执行父类的构造方法
    6.执行子类的构造代码块
    7.第七执行子类的构造方法
    

    总结,也就是说虽然客户端代码是new 的构造方法,但是构造方法确实是在整个实例创建中的最后一个调用
    先静态:具体是先父静态>子静态。
    先父后子:先父的全部,然后后子的全部。
    优先级:父类>子类,静态代码块>非静态代码块>构造函数(与位置前后无关系)

  • 相关阅读:
    虚拟化技术总览
    UNIX环境高级编程笔记之高级I/O
    UNIX环境高级编程笔记之线程
    UNIX环境高级编程笔记之进程控制
    UNIX环境高级编程笔记之进程环境
    mysql中如何删除表上的索引?删除索引?
    linux环境中如何删除文件的前n行?
    linux环境中iostat命令的安装,解决-bash: iostat: command not found问题
    linux环境中安装iotop命令,解决-bash: iotop: command not found问题
    mysql初始化时报错bin/mysqld: error while loading shared libraries: libnuma.so.1: cannot open shared object file: No such file or directory的处理
  • 原文地址:https://www.cnblogs.com/gmhappy/p/11864009.html
Copyright © 2020-2023  润新知