继承类的初始化——java为例

引言

在分析android应用层的代码时,时常遇到类初始化,重载等相关知识点,在此进行总结,该部分内容是对java类的初始化进行总结分析。

1 java继承中的初始化

首先见下图所示:

继承基类B的子类C的对象创建的初始化过程如下:

1、加载子类的C.class文件;

2、通过关键字得知子类C有一个基类B,继续加载基类B的B.class文件;若基类B还有它的上一层基类A则会继续加载A.class;

3、static域的初始化是在所有类的加载完之后就会进行的,最上一层基类A加载完,该类的static域便会初始化,然后再处理第二层基类B的static域,对其进行初始化,直到最下层子类C的static域初始化完成,此时子类C及其所有基类A,B的加载和static域已经初始化完成。

总结:以上三步是在没有创建对象,或者说子类的main方法里没有任何语句时都会执行的,只要运行子类,都会执行类的加载和静态域的初始化。

注意:静态域和实例域(包含成员变量和成员方法)的初始化时机不同,静态域的初始化是在类加载完就一定会进行的,但是实例域的初始化是在创建对象之后才进行的。也就是说,只有在调用构造器时才会进行实例域的初始化。

2 案例参考1

案例代码:(参考:https://blog.csdn.net/chen_yuxi/article/details/81945314

class Insect{
    private int i=9;
    protected int j;
    Insect(){
        System.out.println("i="+i+","+"j="+j);
        j=39;
        System.out.println("i="+i+","+"j="+j);
    }
    private static int x1=printInit("static Insect.x1 initialized");
    static int printInit(String s){
        System.out.println(s);
        return 47;
    }
}
public class Beetle extends Insect {
    private int k=printInit("Beetle.k initialized");
    public Beetle(){
        System.out.println("k="+k);
        System.out.println("j="+j);
    }
    private static int x2=printInit("static Beetle.x2 initialized");
 
}
class Beatles extends Beetle{
    private int m=printInit("beatles.m initialized");//为了证明static和非static域的初始化时机不一样
    private static int x3=printInit("static Beatles.x3 initialized");
    public Beatles(){
        System.out.println("m="+m);
    }
 
    public static void main(String[] args) {
        System.out.println("beatles initialized");
        Beatles b3=new Beatles();//加载类之后static域初始化结束,只有创建对象,调用构造器的时候才会进行初始化。
        System.out.println("x3="+b3.x3);
        //System.out.println(m);
    }
}

输出结果:

static Insect.x1 initialized
static Beetle.x2 initialized
static Beatles.x3 initialized
beatles initialized
i=9,j=0
i=9,j=39
Beetle.k initialized
k=47
j=39
beatles.m initialized
m=47
x3=47

从运行结果可以看出,与我们图中分析的一样。首先从子类开始往上加载所有的类,然后从基类开始逐步初始化static域,最后在main中调用构造器触发该类的实例域初始化,实例域的初始化是从其子类继承的最上层基类开始

2 案例参考2

当父类调用被子类重写的方法时,会出现怎样的情况呢?

可以总结为:

先成员变量再构造方法,先父类再子类

多态表现:有同名方法执行子类的

具体案列如下所示:

class father{
    int a=10;
    int b;
    String c = "I'm father\n";
    private int father=fatherlog("variable father value\n");
    father(){
        log();
    }
    void log(){
        System.out.print(c);
        logout();

    }
    void logout(){
        System.out.print("test father\n");
    }
    int fatherlog(String a){
        System.out.print(a); 
        return 88;
    }
}

public class son extends father{
    private String baseName = "sub";
    private int son=sonlog("variable son value\n");
    son(){
        System.out.print("\nI'm son\n");
    }
    @Override
    void  logout(){
        System.out.print("override test son\n");
        //System.out.print(baseName);
    }
    int sonlog(String a){
        System.out.print(a); 
        return 22;
    }
    public static void main(String[] args){
        new son();
    }
}

输出结果为:

variable father value
I'm father
override test son
variable son value

I'm son

该结果证明了上述中的总结:先加载父类再加载子类,先初始成员化变量再初始化方法。

那我们再来将上述代码修改一下

class father{
    int a=10;
    int b;
    String c = "I'm father\n";
    father(){
        log();
    }
    void log(){
        System.out.print(c);
        logout();

    }
    void logout(){
        System.out.print("test father\n");
    }
}

public class son extends father{
    private String baseName = "sub";
    son(){
        System.out.print("\nI'm son\n");
    }
    @Override
    void  logout(){
        //System.out.print("override test son\n");
        System.out.print(baseName);
    }
    public static void main(String[] args){
        new son();
    }
}

I'm father
null
I'm son

这次的结果,为什么logout的输出为null呢?

原因是这样的,在子类中实例化son,会先父类再子类。父类中初始化变量String c,然后执行father构造函数,在其构造函数中调用log(),log()中会调用logout,由于logout在子类中被重写(多态表现:有同名方法执行子类的),所以会执行子类的logout,但是子类的logout函数中会引用子类的变量String baseName,此时的子类成员变量并没有被初始化,所以会提示:null。证明了:先成员变量再构造方法

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值