代码混合执行顺序

本文通过实例分析了Java和C#中代码的执行顺序,包括实例初始化、继承、this和super的使用、虚方法调用以及类初始化和实例初始化的混合情况。详细解释了在不同场景下,代码执行的逻辑,帮助理解这两门语言的运行机制。

阅读如下代码

class HelloA{
    public HelloA(){
        System.out.println("HelloA");
    }
    {
        System.out.println("I'm A Class");
    }
}
​
class HelloB extends HelloA{
    public HelloB(){
        //super(); // 调用父类构造函数(1)
        System.out.println("HelloB");
    }
    {
        System.out.println("I'm B Class");
    }
}
​
public class TestHelloB{
    public static void main(String[] args) {
        new HelloB();
    }
}

1、代码new的是HelloB  所以进入HelloB类 
                子类的所有构造方法中都有一个隐藏的父类构造函数super()
2、进入HelloB的无参构造中---->super()--->HelloA
实例初始化的顺序
        1>super()
        2>显式赋值
        3>普通成员代码块内容
        4>构造器内容
2和3的位置谁的顺序在前面就谁先执行,但是1和4的顺序是固定的
3、执行HelloA中的代码块---->无参构造----->回到子类
4、执行HelloB中的代码快----->无参构造----->返回main函数
I'm A Class
HelloA
I'm B Class
HelloB

阅读如下代码

public class TestFatherChild {
	public static void main(String[] args) {
		Father f = new Father();//(1)
		Child c = new Child();//(2)
	}
}
class Father {
	public Father(){
		System.out.println("father");
	}
}
class Child extends Father{
	public Child(){
		System.out.println("child");
	}
}
1、语句1进入father类的无参---->先输出fathe
2、语句2进入child类的无参----->有默认的super()---->去父类father
3、没有显式赋值和代码块  所以直接执行构造器内容---->输出father
4、回到child类---->同上  进入无参---->输出child
father
father
child

实例初始化运行结果分析

public class Test01 {
    public static void main(String[] args) {
        new Child("mike");
    }
}
​
class People {
    private String name;
​
    public People() {
        System.out.print("1");
    }
​
    public People(String name) {
        System.out.print("2");
        this.name = name;
    }
}
​
class Child extends People {
    People father;
​
    public Child(String name) {
        System.out.print("3");
        father = new People(name + " F");
    }
​
    public Child() {
        System.out.print("4");
    }
}

1、进入child类---->super()---->进入People类无参
2、输出1---->回到child类----->
3、输出3----->new People  
4、进入Peoper有参---->输出2---->name =mikeF

答案:132

继承、属性同名问题

public class Test02 extends Father{
    private String name = "test";
    
    public static void main(String[] args) {
        Test02 test = new Test02();
        System.out.println(test.getName());
    }
}
class Father {
    private String name = "father";
​
    public String getName() {
        return name;
    }
}

1、进入Test02()----->super()--->进入Father---->x显示赋值name = father------>没有代码块还有构造器内容  所以返回test02

2、name = test   test.getName();------>子类没有  所以去父类找----->这个方法是父类里的所以    name是父类的赋值所以是father

实例初始化

public class Test03 {
​
    public static void main(String[] args) {
        new A(new B());//(1)
    }
}
​
class A {
    public A() {
        System.out.println("A");
    }
​
    public A(B b) {
        this();
        System.out.println("AB");
    }
}
​
class B {
    public B() {
        System.out.println("B");
    }
}
1、(1)开始被混淆了
这样理解   B b = new B();
          A a = new A(b);
从里到外运行
所以显示运行B类  无参  ---->super()没有  所以回到main中
new A();----->有参数  所以是进入A(B b)---->this()是调用A中的无参方法  所以输出A
----->再回到A(B b)中  输出AB
​

答案

B

A

AB

继承

public class Test04 {
    public static void main(String[] args) {
        Father f = new Father();
        Son s = new Son();
        System.out.println(f.getInfo());//1
        System.out.println(s.getInfo());//2
        s.setInfo("尚硅谷");//3
        System.out.println(f.getInfo());//4
        System.out.println(s.getInfo());//3
    }
}
class Father{
    private String info = "atguigu";
    public void setInfo(String info){
        this.info = info;
    }
    public String getInfo(){
        return info;
    }
}
class Son extends Father{
    
}

编译看左边 运行看右边

new 的是father所以  1>是atguigu

2>s.getInfo里面没有getInfo方法 所以去到父类   所以还是atguigu

3>s.setInfo已经在内存中赋值为尚硅谷  所以从s调用的get都变成了尚硅谷

4>f.getInfo还是atguigu没变

5>s.getInfo变成了尚硅谷

答案:

atguigu

atguigu

atguigu

尚硅谷

this和super

public class Test05{
    public static void main(String[] args) {
        Father f = new Father();
        Son s = new Son();
        System.out.println(f.getInfo());//1
        System.out.println(s.getInfo());//2
        s.test();//3
        System.out.println("-----------------");
        s.setInfo("大硅谷");//4
        System.out.println(f.getInfo());//5
        System.out.println(s.getInfo());//6
        s.test();
    }
}
class Father{
    private String info = "atguigu";
    public void setInfo(String info){
        this.info = info;
    }
    public String getInfo(){
        return info;
    }
}
class Son extends Father{
    private String info = "尚硅谷";
    public void test(){
        System.out.println(this.getInfo());
        System.out.println(super.getInfo());
    }
}

1>f.getInfo()-->去到father类调用getInfo ---->输出atguigu

2>s.getInfo()-->去到son类中调用geInfo  类中没有getInfo所以去父类--->父类有getInfo所以调用父类的  --->输出atguigu

3>s.test()  方法中有两个调用this.getInfo和super.getInfo  son类中没有所以去父类  所以两个输出都是atguigu

4>s.setInfo(),s是在内存中新建的一个空间 所以s的setInfo已经变成了“大硅谷”

5>f.getInfo(),没有改变所以还是atguigu

6>s.getInfo(),第四行已经改变了值所以调用s.getInfo是daguigu

7>s.test(),--->到达son中的test方法中当前类没有getInfo所以去父类   

但是s.setInfo已经被赋值了大硅谷  所以输出大硅谷

答案

atguigu
atguigu
atguigu
atguigu
-----------------
atguigu
大硅谷
大硅谷
大硅谷

第6题:this、super、重写

public class Test06 {
    public static void main(String[] args) {
        Father f = new Father();
        Son s = new Son();
        System.out.println(f.getInfo());//1
        System.out.println(s.getInfo());//2
        s.test();//3
        System.out.println("-----------------");
        s.setInfo("大硅谷");//4
        System.out.println(f.getInfo());//5
        System.out.println(s.getInfo());//6
        s.test();//7
    }
}
class Father{
    private String info = "atguigu";
    public void setInfo(String info){
        this.info = info;
    }
    public String getInfo(){
        return info;
    }
}
class Son extends Father{
    private String info = "尚硅谷";
    public void setInfo(String info){
        this.info = info;
    }
    public String getInfo(){
        return info;
    }
    public void test(){
        System.out.println(this.getInfo());
        System.out.println(super.getInfo());
    }
}

1>  atguigu

2>  尚硅谷

3>  尚硅谷     atguigu

4> 已经修改了s.setInfo()所以 s.getInfo是大硅谷

5> atguigu

6> 大硅谷

7> 大硅谷  atguigu

答案:

atguigu
尚硅谷
尚硅谷
atguigu
-----------------
atguigu
大硅谷
大硅谷
atguigu

    

第7题:this

public class Test07 {
    public static void main(String[] args) {
        Father f = new Son();//1
        System.out.println(f.x);//5
    }
}
class Father{
    int x = 10;
    public Father(){
        this.print();//2
        x = 20;
    }
    public void print(){
        System.out.println("Father.x = " + x);
    }
}
class Son extends Father{
    int x = 30;
    public Son(){
        this.print();//3
        x = 40;
    }
    public void print(){
        System.out.println("Son.x = " + x);//4
    }
}

1、第一行是多态  编译看左边  运行看右边   先看左边有啥方法  再看son有没有重写

1>调用son的无参  默认有一个super  所以去到父类  运行顺序  显式赋值  代码块  构造方法

  显示赋值是10  没有代码块  所以是运行构造器   运行第二  第二在son中已经被重写了  所以运行重写了的   跳到第四   代码又是就近原则   这里面x还没赋值所以第一行是son.x=0

2、输出完成之后进入显式赋值  x=30在进入构造方法  所以进入第三  第三跳入第四  所以再次输出son.x=30

3、实例初始化不干涉属性  所以最后f.x=20

第8题:虚方法

public class Test08 {
    public static void main(String[] args) {
        A a1 = new A();//1
        A a2 = new B();//2
        B b = new B();//3
        C c = new C();//4
        D d = new D();//5
        System.out.println("(1)" + a1.show(b));//6
        System.out.println("(2)" + a2.show(d));//7
        System.out.println("(3)" + b.show(c));//8
        System.out.println("(4)" + b.show(d));//9
    }
}
class A{
    public String show(D obj){
        return ("A and D");
    }
    public String show(A obj){
        return "A and A";
    }
}
class B extends A{
    public String show(B obj){
        return "B and B";
    }
    public String show(A obj){
        return "B and A";
    }
}
class C extends B{
    
}
class D extends B{
    
}
a1是A类型的    带入一个b   因为b是B类型的  因为A中没有B类型的方法  可以直接去找他的父类
4同下B类的show(d)先去B类中找找不到接收D类型的 那么向上找  A中也没有   那么就找能接受它的父类 所以是A and D
/*(1)A and A
(2)A and D
(3)B and B
(4)A and D*/

虚方法

public class Test09 {
    public static void main(String[] args) {
        A a1 = new A();//1
        A a2 = new B();//2
        B b = new B();//3
        C c = new C();//4
        D d = new D();//5
        System.out.println("(1)" + a1.show(b));//6
        System.out.println("(2)" + a2.show(d));//7
        System.out.println("(3)" + b.show(c));//8
        System.out.println("(4)" + b.show(d));//9
    }
}
​
class A {
    public String show(C obj) {
        return ("A and C");
    }
​
    public String show(A obj) {
        return "A and A";
    }
}
​
class B extends A {
    public String show(B obj) {
        return "B and B";
    }
​
    public String show(A obj) {
        return "B and A";
    }
}
​
class C extends B {
​
}
​
class D extends B {
​
}

第8   去b找show  b中没有接收C类型的方法  因为B继承了A子类没有就想上找 A有 所以输出

A and  C;

答案:

(1)A and A
(2)B and A
(3)A and C
(4)B and B

类初始化和实例初始化混合

public class Student extends Person {
    public int age = getAge();
    public int getAge() {
        System.out.println("Student getAge() 6");
        return 0;
    }
    static String country = getCountry();

    public static String getCountry() {
        System.out.println("Student getCountry() 7");
        return null;
    }
    static {
        System.out.println("Student 静态代码块 8 ");
    }
    {
        System.out.println("Student 普通代码块 9 ");
    }
    public Student() {
        System.out.println("Student 无参 A");
    }
}
class Student extends Person {
    public int age = getAge();
    public int getAge() {
        System.out.println("Student getAge() 6");
        return 0;
    }
    static String country = getCountry();

    public static String getCountry() {
        System.out.println("Student getCountry() 7");
        return null;
    }
    static {
        System.out.println("Student 静态代码块 8 ");
    }
    {
        System.out.println("Student 普通代码块 9 ");
    }
    public Student() {
        System.out.println("Student 无参 A");
    }
}

先父类后子类  先类初始化后实例初始化

父类 类初始化--->子类初始化--->父类实例初始化----->子类实例初始化(注意重写 如果子类有重写那么就不输出父类直接去子类)

答案:

Person getCountry()  2
Person 静态代码块  3
Student getCountry() 7
Student 静态代码块 8 
Student getAge() 6
Person 普通代码块 4
Person 无参 5
Student getAge() 6
Student 普通代码块 9 
Student 无参 A

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值