面向对象-类的加载和对象的创建(执行顺序分析)


面向对象-类的加载和对象的创建(执行顺序分析)

1.Children类

/**
 * 一、类的加载顺序
 * 1加载器启动找到本类的.class文件,通过extends和implement关键字寻找基类,先加载基类和接口
 * 2先初始化父类的static成员变量static代码块和接口的static变量
 * 3再初始化本类的static成员变量和static代码块
 * 二、类加载之后,对象创建后开始加载
 * 1加载父类的非静态成员变量(静态成员变量在类初始化的时候已经加载,非静态成员变量要随对象的创建而初始化)
 * 2加载父类的构造函数(构造函数在此类的成员变量加载完毕后加载)
 * 3加载本类的非静态成员变量
 * 4加载本类的构造函数
 *
 *
 * static变量和代码块随类的加载而加载(同为static顺序加载)
 * 非static成员变量随对象的创建而加载
 * 成员变量先于构造器加载
 * 方法被调用才执行
 *
 */
public class Children extends Father implements IFather {
    private static int childrenStaticField = Print.printInt("子类静态变量childrenStaticField初始化");
    private int childrenNonStaticField = Print.printInt("子类非静态变量childrenNonStaticField初始化");
    public Children() {
        System.out.println("子类构造方法初始化");
    }
    static {
        System.out.println("子类静态代码块执行");
    }
    static int childrenStaticMethod(){
        System.out.println("子类静态方法执行");
        return 50;
    }
}

2.Father类

package com.example.javabasicdemo.classobject;

public interface IFather {
    /**
     * 接口主体中的每个字段声明都是隐式的public、static 和 final
     * 接口变量是静态的,因为 Java 接口本身不能被实例化;变量的值必须在不存在实例的静态上下文中分配.
     * final 修饰符确保分配给接口变量的值是一个真正的常量,不能被程序代码重新分配.
     */
    int iFatherInt = Print.printInt("接口静态变量初始化");
    // jdk8后接口可以有已实现的默认方法
    default void defaultMethod(){
        System.out.println("接口默认方法defaultMethod执行");
    }
    static void interfaceStaticMethod(){
        System.out.println("接口静态方法interfaceStaticMethod执行" );
    }
}

3.IFather接口

package com.example.javabasicdemo.classobject;

public interface IFather {
    // 接口中的变量默认public static final 修饰,接口不能实例化
    int iFatherInt = Print.printInt("接口静态变量初始化");

    // jdk8后接口可以有已实现的默认方法
    default void defaultMethod(){
        System.out.println("接口默认方法defaultMethod执行");
    }
    static void interfaceStaticMethod(){
        System.out.println("接口静态方法interfaceStaticMethod执行" );
    }
}

4.打印类

package com.example.javabasicdemo.classobject;

/**
 * 打印类
 */
public class Print {
    public static int printInt(String s){
        System.out.println(s);
        return 1;
    }
    // 入口
    public static void main(String[] args) {
        Children c = new Children();
        // 执行后的得到打印结果
    }
}

运行结果

亲自动手,印象更深刻

总结

一、类的加载顺序

  • 1加载器启动找到本类的.class文件,通过extends和implement关键字寻找基类,先加载基类和接口
  • 2先初始化父类的static成员变量static代码块和接口的static变量
  • 3再初始化本类的static成员变量和static代码块
    二、类加载之后,对象创建后开始加载
  • 1加载父类的非静态成员变量(静态成员变量在类初始化的时候已经加载,非静态成员变量要随对象的创建而初始化)
  • 2加载父类的构造函数(构造函数在此类的成员变量加载完毕后加载)
  • 3加载本类的非静态成员变量
  • 4加载本类的构造函数
  • static变量和代码块随类的加载而加载(同为static顺序加载)
  • 非static成员变量随对象的创建而加载
  • 成员变量先于构造器加载
  • 方法被调用才执行

思考

  • 什么时候可以将方法定义为静态方法?
    当一个方法只提供通用的操作流程,而不在内部引用具体对象的数据时,就可以将方法定义为静态方法。
  • 为什么静态方法无法调用非静态方法?
    因为Java不会在调用静态方法时传递this,静态方法内没有this当然无法调用实例相关的一切
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值