Java面试中经常遇到的类执行顺序
2017-04-02 23:10
218 查看
引言:
记得以前面试的时候,会直接给一段代码,这段代码很多地方都有print,所以让我写出现打印出什么,后打印出什么。今天我整理一下单类的情况,继承的情况和一些特殊情况,希望大家看了之后,在面试过程中举一反三,成功规避错误。笔者目前整理的一些blog针对面试都是超高频出现的。大家可以点击链接:http://blog.csdn.net/u012403290单类执行顺序:
下面是我写的一个demo:package com.bw; /** * @author brickworker * 关于类Color的描述:测试单个类的执行顺序问题 */ public class Color { //构造函数 public Color() { System.out.println("构造函数执行"); } //静态代码块 static{ System.out.println("静态代码块执行"); } //非静态代码块 { System.out.println("非静态代码块执行"); } //一般方法 void run(){ System.out.println("一般方法执行"); } public static void main(String[] args) { System.out.println("main方法执行");//这个一定要写在最上面,程序一进入马上就执行,不然会导致结果不准确 Color color = new Color(); color.run(); } } //执行结果: //静态代码块执行 //main方法执行 //非静态代码块执行 //构造函数执行 //一般方法执行
真的觉得是对的么?因为我们main的入口写在了类本身之中。导致结果其实是不准确的。我们换个方式,信建立一个Rundemo来触发执行:
package com.bw; public class RunDemo { public static void main(String[] args) { System.out.println("main方法执行");//这个一定要写在最上面,程序一进入马上就执行,不然会导致结果不准确 Color color = new Color(); color.run(); } } //执行结果: //main方法执行 //静态代码块执行 //非静态代码块执行 //构造函数执行 //一般方法执行
是吧,是不是main方法执行顺序跑到最前面去了呢?前面一种情况是因为main方法放在了目标类中,如果要执行这个main方法,虚拟机会先初始化这个主类,所以会先执行static静态代码块,关于这部分,以后我会写一篇关于虚拟机类加载机制的博文。总之,在看面试题的时候一定要看清楚main方法到底是放在哪里。
继承类执行顺序:
接下来,我们看看继承的情况是如何的,以下是我写的一个继承的demo,这里要强调一点,有写小伙伴为了看的更清楚,父类用system.err.println来打印,导致结果不同,两种输出方式是存在很大差别的,而且实验一定要建立在公平公正的前提下://父类 package com.bw; /** * * @author brickworker * 关于类Father的描述:测试继承执行顺序父类 */ public class Father { //构造函数 public Father() { System.out.println("父类构造函数执行"); } //静态代码块 static{ System.out.println("父类静态代码块执行"); } //非静态代码块 { System.out.println("父类非静态代码块执行"); } //一般方法 void run(){ System.out.println("父类一般方法"); } } //子类 package com.bw; /** * * @author brickworker * 关于类Son的描述:测试继承执行顺序子类 */ public class Son extends Father{ //构造函数 public Son() { System.out.println("子类构造方法"); } //静态代码块 static{ System.out.println("子类静态代码块"); } //非静态代码块 { System.out.println("子类非静态代码块"); } //子类重写一般方法 @Override void run() { System.out.println("子类重写一般方法执行"); } public static void main(String[] args) { System.out.println("main方法执行"); Son son = new Son(); son.run(); } } //执行顺序: //父类静态代码块执行 //子类静态代码块 //main方法执行 //父类非静态代码块执行 //父类构造函数执行 //子类非静态代码块 //子类构造方法 //子类重写一般方法执行
现在,我们把main方法单独拿出来,和上面一样,看看执行结果:
main方法执行 父类静态代码块执行 子类静态代码块 父类非静态代码块执行 父类构造函数执行 子类非静态代码块 子类构造方法 子类重写一般方法执行
总结一下:标准的执行顺序是:当前主程序>父类静态代码块>子类静态代码块>父类非静态代码块>父类构造函数>子类非静态代码块>子类构造方法>子类一般方法。那么把上面的顺序中关于父类执行的去掉,其实也符合我们前面讨论的单个类执行顺序。
注意了!注意了!(敲黑板),上面的也许大家在别的文章中看了不止一遍,那么下面的特殊情况你可能就不太清楚了,因为出现的少,但是我们一次看个透彻。
特殊执行顺序:
其实在类加载机制中,类加载存在主动加载和被动加载(可以不用知道,对下面文章理解不妨碍,只是希望知其然更要知其所以然),在被动加载过程中很多并不会触发初始化,所以在判断被动引用的时候,执行顺序会难很多,主要分为3中情况来具体说明:一、通过子类调用了父类的静态字段,子类不会被初始化
//父类 package com.bw; /** * * @author brickworker * 关于类Father的描述:测试继承执行顺序父类 */ public class Father { public static int father = 100; //静态代码块 static{ System.out.println("父类静态代码块执行"); } } //子类 package com.bw; /** * * @author brickworker * 关于类Son的描述:测试继承执行顺序子类 */ public class Son extends Father{ static{ System.out.println("子类静态代码块"); } } //测试类: package com.bw; public class RunDemo { public static void main(String[] args) { System.out.println("main方法执行"); System.out.println(Son.father);//用子类去调去父类的静态字段 } } //执行结果: //main方法执行 //父类静态代码块执行 //100
从上面可以看出,子类的静态代码都没有执行,说明子类完全没有初始化。
二、类作为数组的组件类型不会触发类初始化:
借用上面单类的Color类:
package com.bw; public class RunDemo { public static void main(String[] args) { System.out.println("main方法执行"); Color[] colors = new Color[5]; } } //执行结果: //main方法执行
上面用Color做为数组的组件,没有执行color的静态方法,说明也没有被初始化。
三、常量池引用也会导致不初始化类
package com.bw; /** * @author brickworker * 关于类Color的描述:测试单个类的执行顺序问题 */ public class Color { public static final String color = "red";//新增一段常量,编译阶段户直接放入常量池 //静态代码块 static{ System.out.println("静态代码块执行"); } } // package com.bw; public class RunDemo { public static void main(String[] args) { System.out.println("main方法执行"); System.out.println(Color.color); } } //执行结果: //main方法执行 //red
从上面的结果可以看出,虽然调用了red,但是并有执行color的静态代码块,说明它没有被初始化。
综上所述,如果把类加载时机和顺序进行结合,那么这样的面试题可能就会难倒一大批人,所以合理分析和总结是非常重要的。关于为什么后面类没有初始化,我想后面如果写java虚拟机类加载机制的时候我们再一起探究下。
好啦,如果你看到了这里,谢谢你对我辛苦劳动肯定,同时祝愿你学习进步,事业顺心。
相关文章推荐
- Java的执行顺序,笔试遇到的问答题(做完这题执行顺序不会再错)
- 谈谈JAVA工程狮面试中经常遇到的面试题目------什么是MVC设计模式
- java面试,经常遇到面试官的问题
- 谈谈JAVA工程狮面试中经常遇到的面试题目------什么是MVC设计模式
- 谈谈JAVA工程狮面试中经常遇到的面试题目------什么是MVC设计模式
- 【转】JAVA中的多线程问题(高级面试中经常遇到)
- 在Android编程或者面试中经常会遇到JAVA 面向对象和集合的知识点
- Java面试系列(一):代码的执行顺序
- [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联(各大公司面试经常遇到)
- 学习总结:java面试方法重写详解,静态代码块和构造方法执行顺序问题
- java面试经常会遇到的一些问题分析
- Android面试之java基础try-catch-finally-return的执行先后顺序问题
- java面试过程中经常遇到的一些试题的总结(1)
- java面试过程中经常遇到的面试题
- JAVA中的多线程问题(高级面试中经常遇到)
- Java异常时,finally 与return 执行顺序
- 分享Java面试中遇到的一些经典算法题目 (转)
- java 构造函数的执行顺序
- Java类被加载时执行的顺序问题
- 分享Java面试中遇到的一些经典算法题目