Java初始化规则都不懂,搞什么开发!
2018-03-24 02:20
411 查看
这个教程,咱们来对Java中设计到的初始化规则,或者说初始化顺序,来做一下汇总,这里我基本上把Java中,默认初始化,静态成员初始化,非静态成员初始化,静态代码块,非静态代码块,以及继承中所涉及到的初始化,都涵盖全了。希望你看到这个教程,能有所收获。(๑´ڡ`๑)
默认初始化
在Java中,一个类的数据成员(成员变量)如果没有指定初始化,那么Java会对其执行默认初始化。基本类型初始化默认值为0,boolean为false,字符串或者对象引用初始化为null。这部分比较简单,看下面这个小列子,相信你应该能直接看出来最后运行的结果。(<_<)
![](https://img-blog.csdn.net/20180324020737267?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1ZmVuZ2p1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
public class InitialValues { boolean t; char c; short s; int i; long l; float f; double d; String str; InitialValues reference;
void printInitialValues() { System.out.printf("%-10s %-5s\n", "boolean:", t); System.out.printf("%-10s %-5s\n", "char:", c); System.out.printf("%-10s %-5s\n", "short:", s); System.out.printf("%-10s %-5s\n", "int:", i); System.out.printf("%-10s %-5s\n", "long:", l); System.out.printf("%-10s %-5s\n", "float:", f); System.out.printf("%-10s %-5s\n", "double:", d); System.out.printf("%-10s %-5s\n", "String:", str); System.out.printf("%-10s %-5s\n", "reference:", reference); }
public static void main(String[] args) { InitialValues iv = new InitialValues(); iv.printInitialValues(); }}
// Output----------------boolean: falsechar: short: 0 int: 0 long: 0 float: 0.0 double: 0.0 String: nullreference: null
非静态成员初始化顺序
在一个类中,非静态成员的初始化,发生在任何方法(包括构造器)被调用之前。并且它们定义的顺序,决定了初始化的顺序。来看下面这个小程序,这里的类,我都用的通用的无实际意义的类,这样能让咱们把注意力放在代码逻辑上。这个小程序,我给你提点要求:你捋一下代码的逻辑,看看能不能直接写出来最后的运行结果。完了把你写的结果和我后面给你的答案对比一下,看看能不能搞对。最后你自己最好能敲敲程序运行一下。( •̀⊿•́)ง
![](https://img-blog.csdn.net/201803240208457?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1ZmVuZ2p1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
class XXX { XXX(String s){ System.out.println("XXX > " + s); }}
class AAA { XXX x001 = new XXX("001"); AAA() { System.out.println("AAA"); XXX x004 = new XXX("004"); } XXX x002 = new XXX("002"); void fff() { System.out.println("fffffffff"); } XXX xxx003 = new XXX("003");}
public class Initialization { public static void main(String[] args) { AAA aaa = new AAA(); aaa.fff(); }}
// Output---------XXX > 001XXX > 002XXX > 003AAAXXX > 004fffffffff
静态成员初始化及对象的创建过程
以名为YYY的类举例:当该类的静态方法(包括main()和构造器,构造器实际上也是静态方法)或者静态成员被调用或访问时,Java虚拟机将载入类所对应的YYY.class文件,并创建其Class类对象,然后该类所有的静态成员将执行初始化。并且静态成员初始化只执行这一次。
静态初始化完成后,该类就做好了创建对象的准备。当调用new YYY()创建对象的时候,首先在堆内存上为YYY对象分配空间,然后执行默认初始化(基本类型初始化为0,引用类型初始化为null)。
之后,按照非静态成员定义顺序,进行指定初始化。
最后执行构造器,完成对象的创建。
还是和上面同样的要求,先捋代码逻辑,再手写结果。 (`・ω・´)ゞ
![](https://img-blog.csdn.net/20180324020957251?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1ZmVuZ2p1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
class XXX { XXX(String s){ System.out.println("XXX > " + s); } void xox(String s){ System.out.println("xox : " + s); }}
class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); AAA() { System.out.println("AAA"); x002.xox("002"); } void aaa() { System.out.println("aaa"); }}
class BBB { static XXX x003 = new XXX("003"); XXX x004 = new XXX("004"); BBB(){ System.out.println("BBB"); x004.xox("004"); } void bbb(){System.out.println("bbb");}}
public class Initialization { public static void main(String[] args) { System.out.println("*********"); new AAA(); System.out.println("========="); new BBB(); a002.aaa(); b002.bbb(); }
AAA a001 = new AAA(); static AAA a002 = new AAA(); static AAA a003= new AAA(); BBB b001 = new BBB(); static BBB b002 = new BBB(); static BBB b003 = new BBB();}
// Output---------XXX > 002XXX > 001AAAxox : 002XXX > 001AAAxox : 002XXX > 003XXX > 004BBBxox : 004XXX > 004BBBxox : 004*********XXX > 001AAAxox : 002=========XXX > 004BBBxox : 004aaabbb
静态块代码初始化
其实,整个static { 静态代码块 } 可以看作是一个静态成员。当一个类需要执行静态初始化时,该类中的静态成员初始化和静态代码块,会按照先后定义的顺序执行。当然,这个流程也是就执行这一次。ღ⊙□⊙╱ 还是老要求......
![](https://img-blog.csdn.net/20180324021032198?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1ZmVuZ2p1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
class XXX { XXX(String s){ System.out.println("XXX > " + s); }}
class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); static XXX x003, x004; static { System.out.println("*********"); x003 = new XXX("003"); x004 = new XXX("004"); XXX x005 = new XXX("005"); System.out.println("========="); /**System.out.println(x006);*/ } static XXX x006 = new XXX("006"); XXX x007 = new XXX("007"); AAA() { System.out.println("AAA"); }}
public class Initialization { static AAA aaa = new AAA(); public static void main(String[] args) { new AAA(); }}
// Output---------XXX > 002*********XXX > 003XXX > 004XXX > 005=========XXX > 006XXX > 001XXX > 007AAAXXX > 001XXX > 007AAA
假如把上面/**System.out.println(x006);*/注释掉的代码解除注释,再运行程序,会发生什么情况?
非静态代码块初始化
{ 非静态代码块 },可以看作一个非静态成员。涉及非静态初始化,也会执行它。和普通的非静态成员初始化一样,它的执行也发生在构造器调用之前,并且每当创建对象之前都会调用。稍微修改下上面的例子,把静态代码块前面的static关键字去掉,并把里面的注释行释放,并添加一行打印语句,如下,对比两个例子输出结果。(=•̀口•́=)
![](https://img-blog.csdn.net/20180324021056846?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1ZmVuZ2p1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
class XXX { XXX(String s){ System.out.println("XXX > " + s); }}
class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); static XXX x003, x004; { System.out.println("*********"); x003 = new XXX("003"); x004 = new XXX("004"); XXX x005 = new XXX("005"); System.out.println("========="); System.out.println(x006); System.out.println(x001); } static XXX x006 = new XXX("006"); XXX x007 = new XXX("007"); AAA() { System.out.println("AAA"); }}
public class Initialization { static AAA aaa = new AAA(); public static void main(String[] args) { new AAA(); }}
// Output-------------XXX > 002XXX > 006XXX > 001*********XXX > 003XXX > 004XXX > 005=========XXX@1540e19dXXX@677327b6XXX > 007AAAXXX > 001*********XXX > 003XXX > 004XXX > 005=========XXX@1540e19dXXX@14ae5a5XXX > 007AAA
继承中涉及的初始化
大的原则是:没有父类,就没子类。初始化,当然要先初始化父类,再初始化子类。继承中如果同时涉及到静态初始化和非静态初始化。初始化的执行流程分两步走:(1)先执行静态初始化。且先静态初始化父类,然后再静态初始化子类。(这一步同样就执行一次)(2)父类执行非静态初始化,然后调用构造方法。接着子类执行非静态初始化,然后调用构造方法。接着下一个子类......以此类推到最后一个子类。 _(•̀ω•́ 」∠)_
![](https://img-blog.csdn.net/20180324021119686?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1ZmVuZ2p1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
class XXX { XXX(String s){ System.out.println("XXX > " + s); }}
class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); AAA() { System.out.println("AAA"); } { System.out.println("*********"); XXX x003 = new XXX("003"); } static XXX x004; static { System.out.println("========="); x004 = new XXX("004"); } static XXX x005 = fff("005"); static XXX fff(String s) { System.out.println("fffffffff"); return new XXX(s); }}
class BBB extends AAA { static XXX x006 = new XXX("006"); XXX x007= new XXX("007"); { System.out.println("+++++++++"); XXX x008 = new XXX("008"); } static XXX x009; static { System.out.println("$$$$$$$$$"); x009 = new XXX("009"); } BBB(){ System.out.println("BBB"); } static XXX x010 = fff("010");}
public class Initialization { public static void main(String[] args) { new BBB(); new BBB(); }}
// Output---------XXX > 002=========XXX > 004fffffffffXXX > 005XXX > 006(9个$符号,博客有问题,不显示9个$)XXX > 009fffffffffXXX > 010XXX > 001*********XXX > 003AAAXXX > 007+++++++++XXX > 008BBBXXX > 001*********XXX > 003AAAXXX > 007+++++++++XXX > 008BBB
拓展一下,假如把上面的父类AAA改为抽象类,运行结果还一样吗?自己求证一下吧。好,暂时先写这么多,希望多多少少帮到了你点什么,后面我想到有需要补充的,我再更新帖子吧。✿✿ヽ(゚▽゚)ノ✿
==========================================================
有条件的小伙伴,可以给打赏点儿支持下,给我些鼓励继续写下去。 (๑´ㅂ`๑́)و✧
默认初始化
在Java中,一个类的数据成员(成员变量)如果没有指定初始化,那么Java会对其执行默认初始化。基本类型初始化默认值为0,boolean为false,字符串或者对象引用初始化为null。这部分比较简单,看下面这个小列子,相信你应该能直接看出来最后运行的结果。(<_<)
public class InitialValues { boolean t; char c; short s; int i; long l; float f; double d; String str; InitialValues reference;
void printInitialValues() { System.out.printf("%-10s %-5s\n", "boolean:", t); System.out.printf("%-10s %-5s\n", "char:", c); System.out.printf("%-10s %-5s\n", "short:", s); System.out.printf("%-10s %-5s\n", "int:", i); System.out.printf("%-10s %-5s\n", "long:", l); System.out.printf("%-10s %-5s\n", "float:", f); System.out.printf("%-10s %-5s\n", "double:", d); System.out.printf("%-10s %-5s\n", "String:", str); System.out.printf("%-10s %-5s\n", "reference:", reference); }
public static void main(String[] args) { InitialValues iv = new InitialValues(); iv.printInitialValues(); }}
// Output----------------boolean: falsechar: short: 0 int: 0 long: 0 float: 0.0 double: 0.0 String: nullreference: null
非静态成员初始化顺序
在一个类中,非静态成员的初始化,发生在任何方法(包括构造器)被调用之前。并且它们定义的顺序,决定了初始化的顺序。来看下面这个小程序,这里的类,我都用的通用的无实际意义的类,这样能让咱们把注意力放在代码逻辑上。这个小程序,我给你提点要求:你捋一下代码的逻辑,看看能不能直接写出来最后的运行结果。完了把你写的结果和我后面给你的答案对比一下,看看能不能搞对。最后你自己最好能敲敲程序运行一下。( •̀⊿•́)ง
class XXX { XXX(String s){ System.out.println("XXX > " + s); }}
class AAA { XXX x001 = new XXX("001"); AAA() { System.out.println("AAA"); XXX x004 = new XXX("004"); } XXX x002 = new XXX("002"); void fff() { System.out.println("fffffffff"); } XXX xxx003 = new XXX("003");}
public class Initialization { public static void main(String[] args) { AAA aaa = new AAA(); aaa.fff(); }}
// Output---------XXX > 001XXX > 002XXX > 003AAAXXX > 004fffffffff
静态成员初始化及对象的创建过程
以名为YYY的类举例:当该类的静态方法(包括main()和构造器,构造器实际上也是静态方法)或者静态成员被调用或访问时,Java虚拟机将载入类所对应的YYY.class文件,并创建其Class类对象,然后该类所有的静态成员将执行初始化。并且静态成员初始化只执行这一次。
静态初始化完成后,该类就做好了创建对象的准备。当调用new YYY()创建对象的时候,首先在堆内存上为YYY对象分配空间,然后执行默认初始化(基本类型初始化为0,引用类型初始化为null)。
之后,按照非静态成员定义顺序,进行指定初始化。
最后执行构造器,完成对象的创建。
还是和上面同样的要求,先捋代码逻辑,再手写结果。 (`・ω・´)ゞ
class XXX { XXX(String s){ System.out.println("XXX > " + s); } void xox(String s){ System.out.println("xox : " + s); }}
class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); AAA() { System.out.println("AAA"); x002.xox("002"); } void aaa() { System.out.println("aaa"); }}
class BBB { static XXX x003 = new XXX("003"); XXX x004 = new XXX("004"); BBB(){ System.out.println("BBB"); x004.xox("004"); } void bbb(){System.out.println("bbb");}}
public class Initialization { public static void main(String[] args) { System.out.println("*********"); new AAA(); System.out.println("========="); new BBB(); a002.aaa(); b002.bbb(); }
AAA a001 = new AAA(); static AAA a002 = new AAA(); static AAA a003= new AAA(); BBB b001 = new BBB(); static BBB b002 = new BBB(); static BBB b003 = new BBB();}
// Output---------XXX > 002XXX > 001AAAxox : 002XXX > 001AAAxox : 002XXX > 003XXX > 004BBBxox : 004XXX > 004BBBxox : 004*********XXX > 001AAAxox : 002=========XXX > 004BBBxox : 004aaabbb
静态块代码初始化
其实,整个static { 静态代码块 } 可以看作是一个静态成员。当一个类需要执行静态初始化时,该类中的静态成员初始化和静态代码块,会按照先后定义的顺序执行。当然,这个流程也是就执行这一次。ღ⊙□⊙╱ 还是老要求......
class XXX { XXX(String s){ System.out.println("XXX > " + s); }}
class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); static XXX x003, x004; static { System.out.println("*********"); x003 = new XXX("003"); x004 = new XXX("004"); XXX x005 = new XXX("005"); System.out.println("========="); /**System.out.println(x006);*/ } static XXX x006 = new XXX("006"); XXX x007 = new XXX("007"); AAA() { System.out.println("AAA"); }}
public class Initialization { static AAA aaa = new AAA(); public static void main(String[] args) { new AAA(); }}
// Output---------XXX > 002*********XXX > 003XXX > 004XXX > 005=========XXX > 006XXX > 001XXX > 007AAAXXX > 001XXX > 007AAA
假如把上面/**System.out.println(x006);*/注释掉的代码解除注释,再运行程序,会发生什么情况?
非静态代码块初始化
{ 非静态代码块 },可以看作一个非静态成员。涉及非静态初始化,也会执行它。和普通的非静态成员初始化一样,它的执行也发生在构造器调用之前,并且每当创建对象之前都会调用。稍微修改下上面的例子,把静态代码块前面的static关键字去掉,并把里面的注释行释放,并添加一行打印语句,如下,对比两个例子输出结果。(=•̀口•́=)
class XXX { XXX(String s){ System.out.println("XXX > " + s); }}
class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); static XXX x003, x004; { System.out.println("*********"); x003 = new XXX("003"); x004 = new XXX("004"); XXX x005 = new XXX("005"); System.out.println("========="); System.out.println(x006); System.out.println(x001); } static XXX x006 = new XXX("006"); XXX x007 = new XXX("007"); AAA() { System.out.println("AAA"); }}
public class Initialization { static AAA aaa = new AAA(); public static void main(String[] args) { new AAA(); }}
// Output-------------XXX > 002XXX > 006XXX > 001*********XXX > 003XXX > 004XXX > 005=========XXX@1540e19dXXX@677327b6XXX > 007AAAXXX > 001*********XXX > 003XXX > 004XXX > 005=========XXX@1540e19dXXX@14ae5a5XXX > 007AAA
继承中涉及的初始化
大的原则是:没有父类,就没子类。初始化,当然要先初始化父类,再初始化子类。继承中如果同时涉及到静态初始化和非静态初始化。初始化的执行流程分两步走:(1)先执行静态初始化。且先静态初始化父类,然后再静态初始化子类。(这一步同样就执行一次)(2)父类执行非静态初始化,然后调用构造方法。接着子类执行非静态初始化,然后调用构造方法。接着下一个子类......以此类推到最后一个子类。 _(•̀ω•́ 」∠)_
class XXX { XXX(String s){ System.out.println("XXX > " + s); }}
class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); AAA() { System.out.println("AAA"); } { System.out.println("*********"); XXX x003 = new XXX("003"); } static XXX x004; static { System.out.println("========="); x004 = new XXX("004"); } static XXX x005 = fff("005"); static XXX fff(String s) { System.out.println("fffffffff"); return new XXX(s); }}
class BBB extends AAA { static XXX x006 = new XXX("006"); XXX x007= new XXX("007"); { System.out.println("+++++++++"); XXX x008 = new XXX("008"); } static XXX x009; static { System.out.println("$$$$$$$$$"); x009 = new XXX("009"); } BBB(){ System.out.println("BBB"); } static XXX x010 = fff("010");}
public class Initialization { public static void main(String[] args) { new BBB(); new BBB(); }}
// Output---------XXX > 002=========XXX > 004fffffffffXXX > 005XXX > 006(9个$符号,博客有问题,不显示9个$)XXX > 009fffffffffXXX > 010XXX > 001*********XXX > 003AAAXXX > 007+++++++++XXX > 008BBBXXX > 001*********XXX > 003AAAXXX > 007+++++++++XXX > 008BBB
拓展一下,假如把上面的父类AAA改为抽象类,运行结果还一样吗?自己求证一下吧。好,暂时先写这么多,希望多多少少帮到了你点什么,后面我想到有需要补充的,我再更新帖子吧。✿✿ヽ(゚▽゚)ノ✿
==========================================================
有条件的小伙伴,可以给打赏点儿支持下,给我些鼓励继续写下去。 (๑´ㅂ`๑́)و✧
相关文章推荐
- Java开发中什么情况下要用到JNI技术??
- 解析Java类和对象的初始化过程_J2EE_Java开发_软件开发-编程-IT资源网
- 微软,您的.net为中国程序员带来了什么?-Java基础-Java-编程开发
- JAVA规则开发篇
- [转载]解析Java类和对象的初始化过程_J2EE_Java开发_软件开发-编程-IT资源网
- Java技术开发规则--中级篇
- Eclipse平台入门之一:什么是Eclipse,我们将开始介绍Java 开发环境(JDE)。
- java 的构造器是干什么用的,初始化对象,还是初始化数据,默认的无参构造器,和有参构造器的区别,找高手解答
- 从java转向C\c++开发要学会些什么
- Android开发Java命名规则
- java开发中遇到的crud命名规则
- java开发中遇到的crud命名规则
- 不懂JAVA中OutputStreamWriter和InputStreamReader到底有什么用?
- JAVA规则--开发篇
- Java编程规则-Java基础-Java-编程开发
- think in java 第5章 完整的JAVA初始化规则
- java开发中的一些规则,或者说是良好的习惯
- Android开发中java 命名规则包的命名
- 最好的Java Web开发的书应该是什么样子?
- Java规则引擎工作原理及其应用-Java基础-Java-编程开发