new一个对象后各代码执行顺序的全过程,详细分析(面向对象语言)

案列分析代码如下:(有需求的可以复制运行一下Java代码)

class Father
{
    Father() {//父类的无参构造方法
        show();
    }
    void show() {
        System.out.println("父类的show方法");
    }
	{
		System.out.println("这是父类代码块");
	}
	static {
		System.out.println("这是父类静态代码块");
	}
}
class Son extends Father
{
    int num = 9;//非static变量
    {
        System.out.println("这是子类的代码块------"+num);
        num = 10;
    }
    Son() {//子类无参构造方法
		//此处有隐藏的	super();
        System.out.println("这是子类的无参构造方法------"+num);
    }
	static {
		 System.out.println("这是子类静态代码块");
	}
	void show() {
		System.out.println("子类的show方法-------" + num);
	}
}
public class demo{
    public static void main(String[] args){
        new Son();
    }
}

运行结果

1本案例分析

new Son();   ==>   找到Son类,到Son()构造方法,首行有隐藏的super();即发现继承了 Father类  ==>  找到Father类,发现Father没有继承其他类,就会默认继承Object类,然后为Object类静态属性分配空间并赋于初值  ==>  回到Father类,执行了Father类的静态代码块,大家会发现,我把Father类的静态代码块写在其他语句下面,还是先执行了它。

static {
    System.out.println("这是父类静态代码块");
}

 

接着又回到Son类,执行Son类的静态代码块

static {
    System.out.println("这是子类静态代码块");
}

 

又回到Father类执行Father类的代码块

{
    System.out.println("这是父类代码块");
}

再执行Father类的构造方法,由于此时构造方法调用了show()方法,而Son类又重写了show()方法,所以会找到Son类的show()方法执行,为什么执行结果是  “子类的show方法-------0”?变量num的值为什么是0,这个我也不知道,希望有大神可以指教一下我。为什么Father类的show()方法没有打印?是因为没有调用它,如果Son类没有重写show()方法,就会执行Father类的show()方法了。

Father() {    //父类的无参构造方法
    show();
}

 

接着继续执行Son类中的非静态属性和代码块

 int num = 9;//非static变量
    {
        System.out.println("这是子类的代码块------"+num);
        num = 10;
    }

 

再执行Son类中的构造方法

Son() {    //子类无参构造方法
		//此处有隐藏的	super();
    System.out.println("这是子类的无参构造方法------"+num);
}

总结,new一个对象时代码的执行顺序

(1)加载父类(以下序号相同,表明初始化是按代码从上到下的顺序来的)

  1.为父类的静态属性分配空间并赋于初值

  1.执行父类静态初始化块;

(2)加载子类

  2.为子类的静态属性分配空间并赋于初值

  2.执行子类的静态的内容;

(3)加载父类构造器

  3.初始化父类的非静态属性并赋于初值

  3.执行父类的非静态代码块;

  4.执行父类的构造方法;

(4)加载子类构造器

  5.初始化子类的非静态属性并赋于初值

  5.执行子类的非静态代码块;

  6.执行子类的构造方法.

总之一句话,静态代码块内容先执行(先父后子),接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。(先父后子)

当然细分加载过程的话,看下面JVM加载过程,静态代码块是在类加载时执行,非静态代码块和加载器在实例初始化时执行。

注意两个问题:

1)静态变量和静态代码块的初始化顺序:谁在前面先初始化谁(这个也比较容易理解,初始化的时候,不可能跳着去初始化吧,比如说静态代码块在静态变量的前面,不可能先跳过静态代码块的初始化先去执行静态变量的初始化吧。)

2)子类的构造方法,不管这个构造方法带不带参数默认的它都会先去寻找父类的不带参数的构造方法。如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
复件 华为面试题.java华为面试题 JAVA方面 1 面向对象的特征有哪些方面 2 String是最基本的数据类型吗? 3 int 和 Integer 有什么区别 4 String 和StringBuffer的区别 5 运行时异常与一般异常有何异同? 异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。 6 说出一些常用的类,包,接口,请各举5个 7 说出ArrayList,Vector, LinkedList的存储性能和特性 ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。 8设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。出程序。 以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。 public class ThreadTest1{ private int j; public static void main(String args[]){ ThreadTest1 tt=new ThreadTest1(); Inc inc=tt.new Inc(); Dec dec=tt.new Dec(); for(int i=0;i<2;i++){ Thread t=new Thread(inc); t.start(); t=new Thread(dec); t.start(); } 微软面试问题。。。。。。。。。。。。。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值