资讯专栏INFORMATION COLUMN

Java初始化规则都不懂,搞什么开发!

qc1iu / 3114人阅读

摘要:静态块代码初始化其实,整个静态代码块可以看作是一个静态成员。和普通的非静态成员初始化一样,它的执行也发生在构造器调用之前,并且每当创建对象之前都会调用。口继承中涉及的初始化大的原则是没有父类,就没子类。

这个教程,咱们来对Java中设计到的初始化规则,或者说初始化顺序,来做一下汇总,这里我基本上把Java中,默认初始化,静态成员初始化,非静态成员初始化,静态代码块,非静态代码块,以及继承中所涉及到的初始化,都涵盖全了。希望你看到这个教程,能有所收获。(๑´ڡ`๑)

默认初始化

在Java中,一个类的数据成员(成员变量)如果没有指定初始化,那么Java会对其执行默认初始化。
基本类型初始化默认值为0,boolean为false,字符串或者对象引用初始化为null。这部分比较简单,看下面这个小列子,相信你应该能直接看出来最后运行的结果。(<_<)

</>复制代码

  1. public class InitialValues {
  2. boolean t;
  3. char c;
  4. short s;
  5. int i;
  6. long l;
  7. float f;
  8. double d;
  9. String str;
  10. InitialValues reference;
  11. void printInitialValues() {
  12. System.out.printf("%-10s %-5s
  13. ", "boolean:", t);
  14. System.out.printf("%-10s %-5s
  15. ", "char:", c);
  16. System.out.printf("%-10s %-5s
  17. ", "short:", s);
  18. System.out.printf("%-10s %-5s
  19. ", "int:", i);
  20. System.out.printf("%-10s %-5s
  21. ", "long:", l);
  22. System.out.printf("%-10s %-5s
  23. ", "float:", f);
  24. System.out.printf("%-10s %-5s
  25. ", "double:", d);
  26. System.out.printf("%-10s %-5s
  27. ", "String:", str);
  28. System.out.printf("%-10s %-5s
  29. ", "reference:", reference);
  30. }
  31. public static void main(String[] args) {
  32. InitialValues iv = new InitialValues();
  33. iv.printInitialValues();
  34. }
  35. }

</>复制代码

  1. // Output
  2. ----------------
  3. boolean: false
  4. char:
  5. short: 0
  6. int: 0
  7. long: 0
  8. float: 0.0
  9. double: 0.0
  10. String: null
  11. reference: null
非静态成员初始化顺序

在一个类中,非静态成员的初始化,发生在任何方法(包括构造器)被调用之前。并且它们定义的顺序,决定了初始化的顺序。来看下面这个小程序,这里的类,我都用的通用的无实际意义的类,这样能让咱们把注意力放在代码逻辑上。这个小程序,我给你提点要求:你捋一下代码的逻辑,看看能不能直接写出来最后的运行结果。完了把你写的结果和我后面给你的答案对比一下,看看能不能搞对。最后你自己最好能敲敲程序运行一下。( •̀⊿•́)ง

</>复制代码

  1. class XXX {
  2. XXX(String s){ System.out.println("XXX > " + s); }
  3. }
  4. class AAA {
  5. XXX x001 = new XXX("001");
  6. AAA() {
  7. System.out.println("AAA");
  8. XXX x004 = new XXX("004");
  9. }
  10. XXX x002 = new XXX("002");
  11. void fff() { System.out.println("fffffffff"); }
  12. XXX xxx003 = new XXX("003");
  13. }
  14. public class Initialization {
  15. public static void main(String[] args) {
  16. AAA aaa = new AAA();
  17. aaa.fff();
  18. }
  19. }

</>复制代码

  1. // Output
  2. ---------
  3. XXX > 001
  4. XXX > 002
  5. XXX > 003
  6. AAA
  7. XXX > 004
  8. fffffffff
静态成员初始化及对象的创建过程

以名为YYY的类举例:

当该类的静态方法(包括main()和构造器,构造器实际上也是静态方法)或者静态成员被调用或访问时,Java虚拟机将载入类所对应的YYY.class文件,并创建其Class类对象,然后该类所有的静态成员将执行初始化。并且静态成员初始化只执行这一次。

静态初始化完成后,该类就做好了创建对象的准备。当调用new YYY()创建对象的时候,首先在堆内存上为YYY对象分配空间,然后执行默认初始化(基本类型初始化为0,引用类型初始化为null)。

之后,按照非静态成员定义顺序,进行指定初始化。

最后执行构造器,完成对象的创建。

还是和上面同样的要求,先捋代码逻辑,再手写结果。 (`・ω・´)ゞ

</>复制代码

  1. class XXX {
  2. XXX(String s){ System.out.println("XXX > " + s); }
  3. void xox(String s){ System.out.println("xox : " + s); }
  4. }
  5. class AAA {
  6. XXX x001 = new XXX("001");
  7. static XXX x002 = new XXX("002");
  8. AAA() {
  9. System.out.println("AAA");
  10. x002.xox("002");
  11. }
  12. void aaa() { System.out.println("aaa"); }
  13. }
  14. class BBB {
  15. static XXX x003 = new XXX("003");
  16. XXX x004 = new XXX("004");
  17. BBB(){
  18. System.out.println("BBB");
  19. x004.xox("004");
  20. }
  21. void bbb(){System.out.println("bbb");}
  22. }
  23. public class Initialization {
  24. public static void main(String[] args) {
  25. System.out.println("*********");
  26. new AAA();
  27. System.out.println("=========");
  28. new BBB();
  29. a002.aaa();
  30. b002.bbb();
  31. }
  32. AAA a001 = new AAA();
  33. static AAA a002 = new AAA();
  34. static AAA a003= new AAA();
  35. BBB b001 = new BBB();
  36. static BBB b002 = new BBB();
  37. static BBB b003 = new BBB();
  38. }

</>复制代码

  1. // Output
  2. ---------
  3. XXX > 002
  4. XXX > 001
  5. AAA
  6. xox : 002
  7. XXX > 001
  8. AAA
  9. xox : 002
  10. XXX > 003
  11. XXX > 004
  12. BBB
  13. xox : 004
  14. XXX > 004
  15. BBB
  16. xox : 004
  17. *********
  18. XXX > 001
  19. AAA
  20. xox : 002
  21. =========
  22. XXX > 004
  23. BBB
  24. xox : 004
  25. aaa
  26. bbb
静态块代码初始化

其实,整个static { 静态代码块 } 可以看作是一个静态成员。当一个类需要执行静态初始化时,该类中的静态成员初始化和静态代码块,会按照先后定义的顺序执行。当然,这个流程也是就执行这一次。ღ⊙□⊙╱ 还是老要求......

</>复制代码

  1. class XXX {
  2. XXX(String s){ System.out.println("XXX > " + s); }
  3. }
  4. class AAA {
  5. XXX x001 = new XXX("001");
  6. static XXX x002 = new XXX("002");
  7. static XXX x003, x004;
  8. static {
  9. System.out.println("*********");
  10. x003 = new XXX("003");
  11. x004 = new XXX("004");
  12. XXX x005 = new XXX("005");
  13. System.out.println("=========");
  14. /**System.out.println(x006);*/
  15. }
  16. static XXX x006 = new XXX("006");
  17. XXX x007 = new XXX("007");
  18. AAA() { System.out.println("AAA"); }
  19. }
  20. public class Initialization {
  21. static AAA aaa = new AAA();
  22. public static void main(String[] args) {
  23. new AAA();
  24. }
  25. }

</>复制代码

  1. // Output
  2. ---------
  3. XXX > 002
  4. *********
  5. XXX > 003
  6. XXX > 004
  7. XXX > 005
  8. =========
  9. XXX > 006
  10. XXX > 001
  11. XXX > 007
  12. AAA
  13. XXX > 001
  14. XXX > 007
  15. AAA
  16. 假如把上面/**System.out.println(x006);*/注释掉的代码解除注释,再运行程序,会发生什么情况?
非静态代码块初始化

{ 非静态代码块 },可以看作一个非静态成员。涉及非静态初始化,也会执行它。和普通的非静态成员初始化一样,它的执行也发生在构造器调用之前,并且每当创建对象之前都会调用。
稍微修改下上面的例子,把静态代码块前面的static关键字去掉,并把里面的注释行释放,并添加一行打印语句,如下,对比两个例子输出结果。(=•̀口•́=)

</>复制代码

  1. class XXX {
  2. XXX(String s){ System.out.println("XXX > " + s); }
  3. }
  4. class AAA {
  5. XXX x001 = new XXX("001");
  6. static XXX x002 = new XXX("002");
  7. static XXX x003, x004;
  8. {
  9. System.out.println("*********");
  10. x003 = new XXX("003");
  11. x004 = new XXX("004");
  12. XXX x005 = new XXX("005");
  13. System.out.println("=========");
  14. System.out.println(x006);
  15. System.out.println(x001);
  16. }
  17. static XXX x006 = new XXX("006");
  18. XXX x007 = new XXX("007");
  19. AAA() { System.out.println("AAA"); }
  20. }
  21. public class Initialization {
  22. static AAA aaa = new AAA();
  23. public static void main(String[] args) {
  24. new AAA();
  25. }
  26. }

</>复制代码

  1. // Output
  2. -------------
  3. XXX > 002
  4. XXX > 006
  5. XXX > 001
  6. *********
  7. XXX > 003
  8. XXX > 004
  9. XXX > 005
  10. =========
  11. XXX@1540e19d
  12. XXX@677327b6
  13. XXX > 007
  14. AAA
  15. XXX > 001
  16. *********
  17. XXX > 003
  18. XXX > 004
  19. XXX > 005
  20. =========
  21. XXX@1540e19d
  22. XXX@14ae5a5
  23. XXX > 007
  24. AAA
继承中涉及的初始化

大的原则是:没有父类,就没子类。初始化,当然要先初始化父类,再初始化子类。
继承中如果同时涉及到静态初始化和非静态初始化。初始化的执行流程分两步走:
(1)先执行静态初始化。且先静态初始化父类,然后再静态初始化子类。(这一步同样就执行一次)
(2)父类执行非静态初始化,然后调用构造方法。接着子类执行非静态初始化,然后调用构造方法。接着下一个子类......以此类推到最后一个子类。 (•̀ω•́ 」∠)

</>复制代码

  1. class XXX {
  2. XXX(String s){ System.out.println("XXX > " + s); }
  3. }
  4. class AAA {
  5. XXX x001 = new XXX("001");
  6. static XXX x002 = new XXX("002");
  7. AAA() {
  8. System.out.println("AAA");
  9. }
  10. {
  11. System.out.println("*********");
  12. XXX x003 = new XXX("003");
  13. }
  14. static XXX x004;
  15. static {
  16. System.out.println("=========");
  17. x004 = new XXX("004");
  18. }
  19. static XXX x005 = fff("005");
  20. static XXX fff(String s) {
  21. System.out.println("fffffffff");
  22. return new XXX(s);
  23. }
  24. }
  25. class BBB extends AAA {
  26. static XXX x006 = new XXX("006");
  27. XXX x007= new XXX("007");
  28. {
  29. System.out.println("+++++++++");
  30. XXX x008 = new XXX("008");
  31. }
  32. static XXX x009;
  33. static {
  34. System.out.println("$$$$$$$$$");
  35. x009 = new XXX("009");
  36. }
  37. BBB(){
  38. System.out.println("BBB");
  39. }
  40. static XXX x010 = fff("010");
  41. }
  42. public class Initialization {
  43. public static void main(String[] args) {
  44. new BBB();
  45. new BBB();
  46. }
  47. }

</>复制代码

  1. // Output
  2. ---------
  3. XXX > 002
  4. =========
  5. XXX > 004
  6. fffffffff
  7. XXX > 005
  8. XXX > 006
  9. $$$$$$$$$
  10. XXX > 009
  11. fffffffff
  12. XXX > 010
  13. XXX > 001
  14. *********
  15. XXX > 003
  16. AAA
  17. XXX > 007
  18. +++++++++
  19. XXX > 008
  20. BBB
  21. XXX > 001
  22. *********
  23. XXX > 003
  24. AAA
  25. XXX > 007
  26. +++++++++
  27. XXX > 008
  28. BBB

拓展一下,假如把上面的父类AAA改为抽象类,运行结果还一样吗?自己求证一下吧。
好,暂时先写这么多,希望多多少少帮到了你点什么,后面我想到有需要补充的,我再更新帖子吧。✿✿ヽ(゚▽゚)ノ✿

============================================================================

有条件的小伙伴,可以给打赏点儿支持下,给我些鼓励继续写下去。 (๑´ㅂ`๑́)و✧

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76368.html

相关文章

  • 【好好面试】学完Aop,连动态代理的原理不懂

    摘要:总结动态代理的相关原理已经讲解完毕,接下来让我们回答以下几个思考题。 【干货点】 此处是【好好面试】系列文的第12篇文章。文章目标主要是通过原理剖析的方式解答Aop动态代理的面试热点问题,通过一步步提出问题和了解原理的方式,我们可以记得更深更牢,进而解决被面试官卡住喉咙的情况。问题如下 SpringBoot默认代理类型是什么 为什么不用静态代理 JDK动态代理原理 CGLIB动态代理...

    Keven 评论0 收藏0
  • 大学一年之后竟如此。。。开学前的挣扎

    摘要:后来知道有了院赛,学长说刷院和杭电就可,我就一直刷院,到最后比赛前院的前五十道基本做完,杭电也弄了十来道,就这样草草参加比赛了。 博客主页: https://b...

    MartinDai 评论0 收藏0
  • 感觉奇怪的地方,必有玄机

    摘要:微信在上一个大版本中将公众号内容的展示更改为信息流模式。克制的努力在本人看来,微信的产品思维真得堪称楷模。你可以仿照微信来搞一个公众号,但如果不懂这些底层的逻辑,即便是输了都不知道输在哪里。 微信在上一个大版本中将公众号内容的展示更改为信息流模式。刚开始还有些不习惯,也不明白为什么要这样做。在使用了一段时间之后,慢慢也就习惯了。但在使用的某一瞬间,潜意识中有一个疑惑:同样是推文,为什么...

    helloworldcoding 评论0 收藏0
  • 从 ++[[]][+[]]+[+[]]==10? 深入浅出弱类型 JS 的隐式转换

    摘要:与此相对,强类型语言的类型之间不一定有隐式转换。三为什么是弱类型弱类型相对于强类型来说类型检查更不严格,比如说允许变量类型的隐式转换,允许强制类型转换等等。在中,加性运算符有大量的特殊行为。 从++[[]][+[]]+[+[]]==10?深入浅出弱类型JS的隐式转换 本文纯属原创? 如有雷同? 纯属抄袭? 不甚荣幸! 欢迎转载! 原文收录在【我的GitHub博客】,觉得本文写的不算烂的...

    miya 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<