Java-类和对象3-继承下的执行顺序

在类当中代码的执行并非是按顺序执行,在程序编译时也是如此。类当中的执行顺序为先静态,再实例,最后构造。我们平常new出的对象调用的构造方法在这里是最后执行的

要了解执行顺序要先知道static,代码块,继承的相关知识

一:static

被static修饰的变量称为静态成员变量或者是类变量(不能用于修饰局部变量),它不在对象所在的堆上而在方法区。它的生命周期伴随类的一生(类的加载而创建,类的卸载而销毁)。被static修饰的变量的特殊在于它不属于对象而属于类,一般用   类名.  的形式访问,静态方法(类方法)的访问也是一样。无论类被实例化多少次,静态成员变量只有一个副本。静态方法调用一次就执行一次

要注意两点

1,因为被static修饰的方法不依赖对象,所以在它的里面不能直接使用类当中的成员方法和成员变量,若要使用可以在内部实例化一个对象

2,因为this是基于对象的,所以无法通过this调用被static修饰的方法或变量

总结就是“静态中不可有非静,非静中可以有静”

二;代码块

代码块有普通代码块、实例代码块(构造块)、静态代码块、同步代码块四种

1,普通代码块:使用在方法或语句内部,它的作用是区分作用范围和限制生命周期。比如

public void func(){
        {
            int a = 10;
            System.out.println(a);  //10 
        }
        System.out.println(a);      //报错 第一个a的作用域为{}中
        int a = 100;
        System.out.println(a);      //100
    }

2,实例代码块:在类中直接用{}圈出一块空间就可以不需要任何的修饰符

public class Test {
    {
        
    }
}

它先于构造方法执行(无论构造方法在前还是实例代码块在前),实例成员变量和实例代码块谁先执行取决与书写顺序

public class Test {
    {
        a = 100;      //未报错
    }
    public int a = 10;
    public static void main(String[] args) {
        Test test = new Test();
        System.out.println(test.a);   //10
    }
}


public class Test {
    public int a = 10;
    {
        a = 100;
    }
    public static void main(String[] args) {
        Test test = new Test();
        System.out.println(test.a);   //100
    }
}

由于Java的编译不是从上到下的,在块中出现“未定义先使用”未报错

3,静态代码块:格式上是static{},类先加载再实例化,静态块在加载时被执行,不依赖对象。同时也是无论类被实例化多少次,静态代码块只执行一次,它也有类似于实例代码块的执行顺序static执行的先后顺序

public class Test {
    public static int a = 10;
    static {
        a = 100;
    }

    public static void main(String[] args) {
        System.out.println(Test.a);    //100
    }
}


public class Test {
    static {
        a = 100;     //未报错
    }
    public static int a = 10;
    public static void main(String[] args) {
        System.out.println(Test.a);     //10
    }
}

4,同步代码块(线程相关):格式

public class Test {
    synchronized (监视器){
        
    }
}

三:具体问题

在父类的构造方法中调用子类重写父类的方法

public class Fu {
    int a = 10;
    public Fu(){
        print_a();
    }
    void print_a(){
        System.out.println(a);
    }
}
public class Zi extends Fu{
    int a = 100;

    @Override
    void print_a() {
        System.out.println(a);
    }

    public static void main(String[] args) {
        Zi zi = new Zi();     //0
    }
}

代码的运行结果为输出0,在多态现象下并没有输出100

原因在于在父类的构造方法中调用子类重写父类的方法,会调用子类的方法(动态绑定),但此时还在执行父类的构造(先构造完父类再是子类),子类并没有构造完。如果此时掉用子类的成员变量将出现调用的成员变量是默认值的情况。

四:总结

1,在继承的环境下大方向是先父后子、先静态,后实例,最后构造

2,具体为     父静态--->子静态--->父实例--->父构造--->子实例--->子构造

静态指:静态方法、静态变量、静态代码块

实例指:实例成员变量、实例化类、实例代码块

构造指:构造方法

不同等级的执行顺序为上面所示,但同级别的执行顺序是按照代码的书写顺序执行像前面的实例代码块和静态代码块图片中展示的一样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值