JAVA面试习题解惑系列(一)——类的初始化顺序-JAVA程序员JAVA工程师面试必看_第1页
JAVA面试习题解惑系列(一)——类的初始化顺序-JAVA程序员JAVA工程师面试必看_第2页
JAVA面试习题解惑系列(一)——类的初始化顺序-JAVA程序员JAVA工程师面试必看_第3页
JAVA面试习题解惑系列(一)——类的初始化顺序-JAVA程序员JAVA工程师面试必看_第4页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、-JAVA程序员JAVA工程师面试必看JAVA面试题解惑系列(一)类的初始化顺序关键字: java 面试题 初始化 作者:臧圩人(zangweiren) 网址: >>>转载请注明出处!<<< 大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果。这实际上是在考查我们对于继承情况下类的初始化顺序的了解。 我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化

2、顺序依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器。我们也可以通过下面的测试代码来验证这一点: Java代码 1. public class InitialOrderTest    2.   3.     / 静态变量   4.     public static String staticField = "静态变量" &

3、#160; 5.     / 变量   6.     public String field = "变量"   7.   8.     / 静态初始化块   9.     static    10.    &#

4、160;    System.out.println(staticField);   11.         System.out.println("静态初始化块");   12.        13.   14.     / 初始化块   15.  

5、0;     16.         System.out.println(field);   17.         System.out.println("初始化块");   18.        19.   20.    &

6、#160;/ 构造器   21.     public InitialOrderTest()    22.         System.out.println("构造器");   23.        24.   25.     public

7、60;static void main(String args)    26.         new InitialOrderTest();   27.        28.   public static String staticField = "静态变量"/ 变量public String field = "变

8、量"/ 静态初始化块static System.out.println(staticField);System.out.println("静态初始化块");/ 初始化块System.out.println(field);System.out.println("初始化块");/ 构造器public InitialOrderTest() System.out.println("构造器");public static void main(String args) new InitialOrderTest();运行以上代码,我们会得

9、到如下的输出结果: 1. 静态变量 2. 静态初始化块 3. 变量 4. 初始化块 5. 构造器 这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果: Java代码 1. class Parent    2.     / 静态变量   3.     public static String p_StaticField = "父类-静态变量"

10、;   4.     / 变量   5.     public String p_Field = "父类-变量"   6.   7.     / 静态初始化块   8.     static    9.   &

11、#160;     System.out.println(p_StaticField);   10.         System.out.println("父类-静态初始化块");   11.        12.   13.     / 初始化块   14

12、.        15.         System.out.println(p_Field);   16.         System.out.println("父类-初始化块");   17.        18.   19. &#

13、160;   / 构造器   20.     public Parent()    21.         System.out.println("父类-构造器");   22.        23.   24.   25. public&

14、#160;class SubClass extends Parent    26.     / 静态变量   27.     public static String s_StaticField = "子类-静态变量"   28.     / 变量   29. 

15、0;   public String s_Field = "子类-变量"   30.     / 静态初始化块   31.     static    32.         System.out.println(s_StaticField);   

16、33.         System.out.println("子类-静态初始化块");   34.        35.     / 初始化块   36.        37.         System.

17、out.println(s_Field);   38.         System.out.println("子类-初始化块");   39.        40.   41.     / 构造器   42.     public SubClass()

18、60;   43.         System.out.println("子类-构造器");   44.        45.   46.     / 程序入口   47.     public static void main(Stri

19、ng args)    48.         new SubClass();   49.        50.   class Parent / 静态变量public static String p_StaticField = "父类-静态变量"/ 变量public String p_Field = "父类-变量"/ 静态初始

20、化块static System.out.println(p_StaticField);System.out.println("父类-静态初始化块");/ 初始化块System.out.println(p_Field);System.out.println("父类-初始化块");/ 构造器public Parent() System.out.println("父类-构造器");public class SubClass extends Parent / 静态变量public static String s_StaticField = &

21、quot;子类-静态变量"/ 变量public String s_Field = "子类-变量"/ 静态初始化块static System.out.println(s_StaticField);System.out.println("子类-静态初始化块");/ 初始化块System.out.println(s_Field);System.out.println("子类-初始化块");/ 构造器public SubClass() System.out.println("子类-构造器");/ 程序入口publ

22、ic static void main(String args) new SubClass();运行一下上面的代码,结果马上呈现在我们的眼前: 1. 父类-静态变量 2. 父类-静态初始化块 3. 子类-静态变量 4. 子类-静态初始化块 5. 父类-变量 6. 父类-初始化块 7. 父类-构造器 8. 子类-变量 9. 子类-初始化块 10. 子类-构造器 现在,结果已经不言自明了。大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。 那么对于静态变量和静态初始化块之间、变量

23、和初始化块之间的先后顺序又是怎样呢是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢实际上这取决于它们在类中出现的先后顺序。我们以静态变量和静态初始化块为例来进行说明。 同样,我们还是写一个类来进行测试: Java代码 1. public class TestOrder    2.     / 静态变量   3.     public static TestA a = 

24、new TestA();   4.        5.     / 静态初始化块   6.     static    7.         System.out.println("静态初始化块");   8.    &

25、#160;   9.        10.     / 静态变量   11.     public static TestB b = new TestB();   12.   13.     public static void main(

26、String args)    14.         new TestOrder();   15.        16.   17.   18. class TestA    19.     public TestA()    

27、20.         System.out.println("Test-A");   21.        22.   23.   24. class TestB    25.     public TestB()    26.   &#

28、160;     System.out.println("Test-B");   27.        28.   public class TestOrder / 静态变量public static TestA a = new TestA();/ 静态初始化块static System.out.println("静态初始化块");/ 静态变量public static TestB b = new Test

29、B();public static void main(String args) new TestOrder();class TestA public TestA() System.out.println("Test-A");class TestB public TestB() System.out.println("Test-B");运行上面的代码,会得到如下的结果: 1. Test-A 2. 静态初始化块 3. Test-B 大家可以随意改变变量a、变量b以及静态初始化块的前后位置,就会发现输出结果随着它们在类中出现的前后顺序而改变,这就说明静态变量

30、和静态初始化块是依照他们在类中的定义顺序进行初始化的。同样,变量和初始化块也遵循这个规律。 了解了继承情况下类的初始化顺序之后,如何判断最终输出结果就迎刃而解了。 · 10:13 · 浏览 (4106) · 评论 (41) · 分类: JAVA面试题解惑系列 · 收藏 · 相关推荐 评论zm2693450 2008-07-14 好贴,顶起来臧圩人 2008-07-08 回复 狂放不羁: 总结的很好,赞一个狂放不羁 2008-07-08 静态代码为什么先于非静态代码这是因为静态代码是在类加载完毕后执行的,而加载类的顺序是先父类后子类,所

31、以静态代码的执行是先执行父类的,然后执行子类的。对于非静态变量以及实例初始化块都是在构造函数里的代码执行前执行。所以静态代码是在类加载后执行,而实例代码是在构造函数执行前执行。但是当我们显示控制类加载的时候情况有点变化,显示加载可以有关两种方法:第一种:利用forName方法当我们查API文档就会发现forName方法有两种形式。分别如下:public static Class<> forName(String className)throws ClassNotFoundExceptionpublic static Class<> forName(String name

32、,boolean initialize,ClassLoader loader)throws ClassNotFoundException 第二个方法值得注意的就是第二个参数boolean initialize,如果我们把这个参数设置为false,那么当我们加载完类后就不会执行静态代码和静态的初始化动作。只有当我们new一个对象的时候才会初始化。而第三个参数是用来指明类的加载器的。如果查看java.lang.Class类的源代码,上述两种方法最终都会调用Class类中的私有的native方法forName0(),此方法的声明如下:private static native Class forNa

33、me0(String name, boolean init , ClassLoader loader)throws ClassNotFoundException; 所以当我们调用Class.forName(name )时,其实是在方法内部调用了:forName0(name, true, ClassLoader.getCallerClassLoader();当我们调用Class.forName(name, initialize, loader )的时候,实际上此方法内部调用了:forName0(name, initialize, loader); 第二种:利用Class对象获取的ClassLoader装载。 此方法也是在实例化时才执行静态代码的执行。综上所述可以总结如下:1 对于隐式的加载(new一个对象和调用类的静态方法),静态代码是在类加载后立刻执行,而对于显示加载(第一种是用j

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论