这里主要学习初始化,分为:
1.变量初始化
2.构造函数初始化
3.数组初始化
4.继承初始化
1.变量初始化
成员初始化分为两种:
(1)成员变量初始化
在定义成员变量时,如果没有给变量赋于初始值,系统会给出一个默认值。
这里有两种选择:要么使用系统的默认初始值,要么自己定义初始值。
系统给出的默认输出值为:
boolean false char [ ] byte 0 short 0 int 0 long 0 float 0.0 double 0.0 refenece null
char初始值为0,显示为空白;String 引用类型默认初始时为null
(2)局部变量初始化
局部变量在使用“基本类型“时必须富商初始值,否则编译器会报错。
2.构造函数初始化
(1)成员变量在任何构造函数调用之前被初始化,如:
class Init2 { private int i; public Init2(int i) { this.i = i; } public static void main(String[] args) { new Init2(3); } private String reference; }
1).i 在构造函数调用之前已经被赋予初始值0,然后才在构造函数中赋于新值3。
2).不管成员变量散落什么地方,都能够首先初始化。
3).变量的定义顺序决定了初始化的顺序。
(2)静态数据库的初始化
这里使用“Java编程思想”的例子
class Bowl { public Bowl(int maker) { // maker用于标记 System.out.println("Bowl(" + maker +")"); } public void f1(int maker) { System.out.println("f1(" + maker +")"); } } class Table { static Bowl bowl1 = new Bowl(1); // 静态成员变量 public Table() { System.out.println("Table"); bowl1.f1(1); } public void f2(int maker) { System.out.println("f2(" + maker +")"); } static Bowl bowl2 = new Bowl(2); // 静态成员变量 } class Cupboard { Bowl bowl3 = new Bowl(3); // 非静态成员变量 static Bowl bowl4 = new Bowl(4); // 静态成员变量 public Cupboard() { System.out.println("Table"); bowl3.f1(2); } public void f3(int maker) { System.out.println("f3(" + maker +")"); } static Bowl bowl5 = new Bowl(5); // 静态成员变量 } class Init3 { public static void main(String[] args) { System.out.println("Init3.main()"); new Cupboard(); System.out.println("Init3.main()"); new Cupboard(); table.f2(1); cupboard.f3(1); } static Table table = new Table(); static Cupboard cupboard = new Cupboard(); }
执行结果:
Bowl(1) Bowl(2) Table f1(1) Bowl(4) Bowl(5) Bowl(3) Cupboard f1(2) Init3.main() Bowl(3) Cupboard f1(2) Init3.main() Bowl(3) Cupboard f1(2) f2(1) f3(1)
说明:
第一步:首先初始化 static Table table = new Table(); (因为 在调用 Init3 main有静态变量)
1.1.在Table中初始化 static Bowl bowl1 = new Bowl(1);,此时,输出的结果为:Bowl(1)
1.2.在Table中初始化 static Bowl bowl2 = new Bowl(2);,此时,输出的结果为:Bowl(2)
1.3.初始化Table的构造函数,输出: Table,并执行 bowl1.f1(1) 方法,输出:f1(1)
所以在执行完成 static Table table = new Table(); 后,输出结果为:
Bowl(1) Bowl(2) Table f1(1)
第二步:初始化 static Cupboard cupboard = new Cupboard();
2.1.在Cupboard中初始化 static Bowl bowl4 = new Bowl(4);,此时,输出结果为:Bowl(4)
2.2.在Cupboard中初始化 static Bowl bowl5 = new Bowl(5);,此时,输出结果为:Bowl(5)
2.3.在Cupboard中初始化 Bowl bowl3= new Bowl(3);,此时,输出结果为:Bowl(3)。(虽然bowl3在bowl4 和bowl5前面,但是却在之后初始化。。)
2.4.初始化Cupboard 的构造函数,输出: Cupboard,并执行 bowl3.f1(2) 方法,输出:f1(2)
所以在执行完成static Cupboard cupboard = new Cupboard();后,输出结果为:
Bowl(4) Bowl(5) Bowl(3) Cupboard f1(2)
第三步:执行main函数的打印,输出:Init3.main()
第四步:执行 new Cupboard();(这里不执行静态成员变量bowl4 和bowl5,是因为已经被初始化,不需要在执行)
4.1.在Cupboard中初始化 Bowl bowl3= new Bowl(3);,此时,输出结果为:Bowl(3)。
4.2.初始化Cupboard 的构造函数,输出: Cupboard,并执行 bowl3.f1(2) 方法,输出:f1(2)
输出结果:
Bowl(3) Cupboard f1(2)
第五步:执行main函数的打印,输出:Init3.main()
第六步:执行 new Cupboard();(这里不执行静态成员变量bowl4 和bowl5,是因为已经被初始化,不需要在执行)
6.1.在Cupboard中初始化 Bowl bowl3= new Bowl(3);,此时,输出结果为:Bowl(3)。
6.2.初始化Cupboard 的构造函数,输出: Cupboard,并执行 bowl3.f1(2) 方法,输出:f1(2)
输出结果:
Bowl(3) Cupboard f1(2)
第七步:执行 table.f2(1); 输出:f2(1)
第八步:执行cupboard.f3(1); 输出:f3(1)
小节:初始化顺序先是静态对象(前提是该对象没有被初始化),然后是非静态对象。
(3)静态块初始化
在类中使用 static{….} 表示静态块,将在使用该类之前的数据初始化。
静态块与静态变量一样,只初始化一次。并且,执行顺序是按照位置从上往下执行,即:静态块与静态方法优先级相同。
触发条件:
1.首次生成这个类的对象;
2.首次访问属于这个类的静态成员。
class StaticBlock { public static String s = "StaticBlock"; static { System.out.println("StaticBlock.enclosing_method()"); } } class InvokeStaticBlock { public static void main(String[] args) { new StaticBlock(); // 生成对象的引用 String ss = StaticBlock.s; // 使用该对象的静态成员 } }
总结:
对象创建流程:
1.当创建对象实例时,会去执行构造函数(构造函数可以看成是静态方法),Java解释器必须找到类路径,以定位到该类的.class文件;
2.加载class文件,并初始化所有静态数据。因此,静态初始化只有在class对象首次加载时执行一次,后面再次加载不再执行初始化操作;
3.创建对象时,会在堆上分配足够的存储空间;
4.这块存储空间会被清零,将基本类型数据附上初始值,引用类型置为null;
5.执行所有出现与字段定义处的初始化动作,即如果字段有初始值,即修改默认初始值,赋于新值;
6.执行构造函数。