黑马程序员技术交流社区

标题: 关于子父类构造代码块,构造函数 [打印本页]

作者: 陈祥厅    时间: 2013-1-13 18:10
标题: 关于子父类构造代码块,构造函数
public class ExA {  
    private static ExA a = new ExA();  
    static {  
        System.out.println("父类--静态代码块");  
    }  
  
    public ExA() {  
        System.out.println("父类--构造函数");  
    }  
  
    {  
        System.out.println("父类--非静态代码块");  
    }  
  
    public static void main(String[] args) {  
        new ExB();  
    }  
}  
  
class ExB extends ExA {  
    private static ExB b = new ExB();  
    static {  
        System.out.println("子类--静态代码块");  
    }  
    {  
        System.out.println("子类--非静态代码块");  
    }  
  
    public ExB() {  
        System.out.println("子类--构造函数");  
    }  
}  

-------------------------------
执行结果是
父类--非静态代码块
父类--构造函数
父类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数 -----------------------------------为什么非静态在静态前面执行了呢,求执行流程
作者: 黑马刘杰    时间: 2013-1-13 19:40
本帖最后由 黑马刘杰 于 2013-1-13 19:44 编辑
  1. public class ExA {
  2. //第一步:在类加载时执行static类型,当new ExA();时先执行代码块,后执行构造方法。
  3. //第一步输出如下结果:
  4. /*
  5. * 父类--非静态代码块
  6. * 父类--构造函数
  7. */
  8. private static ExA a = new ExA();
  9. //第二步:执行下一条static类型代码输出:
  10. /*
  11. * 父类--静态代码块
  12. */
  13. static {
  14. System.out.println("父类--静态代码块");
  15. }

  16. public ExA() {
  17. System.out.println("父类--构造函数");
  18. }

  19. {
  20. System.out.println("父类--非静态代码块");
  21. }
  22. //第三步:执行main()方法
  23. public static void main(String[] args) {
  24. //然后new ExB(),这时需先加载类ExB的内容,所以执行类加载,
  25. //类加载时执行private static ExB b = new ExB();new ExB()时因为ExB继承自ExA,所以先new ExA()输出:
  26. /*
  27. * 父类--非静态代码块
  28. * 父类--构造函数
  29. */
  30. //然后new ExB(),输出
  31. /*
  32. * 子类--非静态代码块
  33. * 子类--构造函数
  34. */
  35. //然后执行static代码块,输出:
  36. /*
  37. * 子类--静态代码块
  38. */
  39. //类加载完成后才是真正的new ExB(),先new ExA(),输出:
  40. /*
  41. * 父类--非静态代码块
  42. * 父类--构造函数
  43. */
  44. //再new ExB(),输出:
  45. /*
  46. * 子类--非静态代码块
  47. * 子类--构造函数
  48. */
  49. new ExB();
  50. }
  51. }

  52. class ExB extends ExA {
  53. private static ExB b = new ExB();
  54. static {
  55. System.out.println("子类--静态代码块");
  56. }
  57. {
  58. System.out.println("子类--非静态代码块");
  59. }

  60. public ExB() {
  61. System.out.println("子类--构造函数");
  62. }
  63. }

复制代码
总结一点:在类加载时先执行static代码,再执行代码块。
在new一个对象时,不用执行static代码了,先执行代码块,然后执行构造方法。
作者: 陈祥厅    时间: 2013-1-13 19:46
黑马刘杰 发表于 2013-1-13 19:40
总结一点:在类加载时先执行static代码,再执行代码块。
在new一个对象时,不用执行static代码了,先执行代 ...

new一个对象前类不是要先加载好的么
作者: 陈祥厅    时间: 2013-1-13 19:49
黑马刘杰 发表于 2013-1-13 19:40
总结一点:在类加载时先执行static代码,再执行代码块。
在new一个对象时,不用执行static代码了,先执行代 ...

仔细看了下~懂了~3Q
作者: 黄金龙    时间: 2013-1-13 20:13
怎么感觉你的代码很乱的.....我写一个给你看看
作者: 黄金龙    时间: 2013-1-13 20:25
本帖最后由 黄金龙 于 2013-1-13 20:42 编辑
  1. class Parent
  2. {
  3. static
  4. {
  5. System.out.println("父类--静态代码块");
  6. }
  7. {
  8. System.out.println("父类--非静态代码块");
  9. }
  10. public Parent()
  11. {
  12. System.out.println("父类--构造函数");
  13. }
  14. }

  15. class Child extends Parent{

  16. static
  17. {
  18. System.out.println("子类--静态代码块k");
  19. }
  20. {
  21. System.out.println("子类--非静态代码块");
  22. }
  23. public Child()
  24. {
  25. System.out.println("子类--构造函数");
  26. }
  27. }

  28. public class Test
  29. {
  30. public static void main(String[] args)
  31. {
  32. new Child();//创建子类对象...
  33. }
  34. }
复制代码
对象的初始化顺序:
首先执行父类静态的内容,父类静态的内容执行完毕后,
接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,
再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,
父类的非静态代码块执行完毕,
接着执行父类的构造方法;
父类的构造方法执行完毕之后,
它接着去看子类有没有非静态代码块,
如果有就执行子类的非静态代码块。
子类的非静态代码块执行完毕再去执行子类的构造方法

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

test.jpg (11.71 KB, 下载次数: 74)

test.jpg

作者: 陈祥厅    时间: 2013-1-13 22:07
黄金龙 发表于 2013-1-13 20:25
对象的初始化顺序:
首先执行父类静态的内容,父类静态的内容执行完毕后,
接着去执行子类的静态的内容,当 ...

你的代码和我的不一样.......
作者: 黄金龙    时间: 2013-1-13 22:33
陈祥厅 发表于 2013-1-13 22:07
你的代码和我的不一样.......

是不一样....但是..我写那个是最简单的初始化.
作者: 陈祥厅    时间: 2013-1-14 00:37
黄金龙 发表于 2013-1-13 22:33
是不一样....但是..我写那个是最简单的初始化.

目的不是要简单的初始化啊,是要搞明白执行顺序
作者: 折纸时代    时间: 2013-1-14 22:17
感觉你代码有点乱..
A类为公开类,并有主方法体了,那B类继承了A类.B类中没有主方法.
你这样继承,那有什么意义呢?  因为A类自身就可以调用自身的成员,B类继承A类 就无意义了.
关于静态初始化块,是在运行public 类时执行的,
除开其他的不说,单说静态初始化块,可以说是看得见的最先执行.

1.主方法存在的类加载进内存,然后开始执行此类的最高级父类中的静态初始化块(如果有的话)
2.所以此类的所有父类中的静态初始化块全部执行完毕后,菜开始非静态初始化块.
    因为,初始化块相当于 构造器的抽象,在通过new调用构造器时,不同形参的构造器如果存在相同
    的执行体,那么就可以把它们放入初始化块中,优先于构造器先执行.
3.因为父类中也可能存在非静态的初始化块,所以所有类中的静态初始化块执行完毕后
    那么就继续从该类的顶级父类中执行非静态初始化块,因为父类中的构造器运行顺序低于本类
    初始化块,但高于子类初始化块.所以顶级父类的非静态初始化块执行完毕后,就直接执行该类中的构造器,
    然后,向下开始依次以相同的方法执行..
4.如果,在主方法中new两个相同子类的对象,那么因为静态初始化块是在加载类时就完毕了,所以不会随着二次new对象来再次执行
    但是,非静态初始化块和,构造器却会随着对象的创建再次执行..

写的有点多.. 应该还算详细吧.




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2