初始化
Java尽力保证变量在使用前得到恰当的初始化。
未初始化的局部变量将会显示为编译错误。
引用的默认初始值为“null”
指定初始化:
- 使用new(指定构造器)
- 使用方法(方法需要返回值,可选传参)
- 向前引用没有被初始化或定义的值将会抛出异常
构造器初始化
自动初始化(默认初始化)将在构造器被调用之前进行,因此是无法阻止的。
- 初始化顺序
- 变量定义的先后顺序决定了初始化的顺序,即使变量定义散布于方法定义之间,仍旧会在任何方法被调用之前得到初始化。
- 在定义域的时候不指定默认值,将确保变量得到正确的初始化。
静态数据的初始
- 静态数据只占用一份存储区域。
- static关键字不能用于局部变量,只能用于作用域。
- 静态基本类型如果没有得到手动初始化,将会自动获得基本类型的标准初始值。
- 静态初始化只有在必要时可才会进行,如创建了包含静态类的对象。
- 初始化顺序
- 静态对象
- 非静态对象。
对象创建过程:
假设现有类Dog:
- 即使没有显示使用static关键字,构造器实际上也是静态方法。当首次创建Dog类的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域被首次访问时,java解释器必须查找类路径,以定位Dog.class文件。
- 载入Dog.class(创建Class对象),有关静态初始化的所有动作都会执行。因此静态初始化只在Class对象首次加载的时候进行一次。
- 用new Dog()创建对象的时候,将在堆上为Dog对象分配足够的存储空间
- 此”块“存储空间被清零,自动将堆上Dog对象中的所有基本类型数据设为默认值(数字,布尔,字符都相同),引用设置为null
- 执行字段定义出的初始化动作。
- 执行构造器。将会牵扯很多动作。
显式的静态初始化:
Java允许多个静态初始化动作组织成一个特殊的“静态子句”(静态快),如
Public class spoon {
Static int I;
Static {
I = 47;
}
}//…
Static 关键字后面跟随的代码仅仅在这个类的对象被首次生成或被首次访问的时候生成一次,与其他静态初始化动作一致。
非静态实例初始化
实例初始化的类似语法被用来初始化每一个对象的非静态变量。如:
myObject = new Object(1)
匿名内部类必须使用此语法初始化。
数组初始化:
声明数组引用的方括号[]可以置于标识符后面,如:
Int[] a;
或
Int a[];
编译器不允许指定数组的大小。因为:
- 现在拥有的只是对数组的一个引用,也已经为该数组分配了足够的存储空间
- 但是数组对象本身没有分配任何空间。
- 初始化表达式可以为数组对象分配存储空间。如
- Int[] al = {1, 2, 3, 4, 5};
- 定义两个数组引用,如果其中一个使用了
- 初始化表达式,而另一个没有,那么将初始化后过的引用赋值给另一个没有使用初始化表达式的引用,实际上只是复制了一个引用。如:
Int[] a2;
A2 = a1;
- 那么通过a2对对象做出动作将会直接影响使用a1引用的结果,因为操纵的是同一个对象。
- 所有数组都包含一个故又成员,用来获得数组内包含了多少个元素。但不能对其直接修改。改成员即length。
- 数组计数从0开始,即最大可使用下标数为length-1。C和C++接收超出这个边界的操作,但是Java将会抛出异常。因此Java相对稳定。
- 如在编写程序显示不确定数组内需要多少元素,可在运行时使用new创建。如:
Int[] a = new int[26];
- 如创建了非基本类型的数组,便是创建了引用数组。如:
Integer[] a = new Integer[555];
- 初始化进程直到自动包装器类将创建好的对象赋值给引用之后才算结束。
- 如果忘记创建对象,并试图使用数组中的空引用,将会抛出异常。
- 也可以使用{}内的列表来初始化数组。有两种形式:
Integer[] a = {
New Integer(1),
New Integer(2),
3, // Autoboxing
}
或
Integer[] b = new Integer[]{
New Integer(1),
New Integer(2),
3,// AutoBoxing
}
- 列表最后的逗号可选
- 第一种形式只允许用于数组定义处。
- 在没有重写toString方法打印object的时候,默认行为是打印类的名字和对象的地址。
JAVA SE5 之后,可以利用新特性定义可变参数列表,如:
printArray(new object(), new object(), new object());
或
printArray((Object[])new Integer[]{1,2,3,4});
并有:
Public class NewVarArgs {
Static viod printArray(Object… args){
// your own operation;
}
- 这里,printArray方法的参数声明的写法即为可变参数列表。
- 指定参数是,编译器实际上会填充数组,获取得到的人就是一个数组,且sforeach可以进行迭代。
- 第二种方法将自动包装器转型为Object
- 0个参数传递给可变参数列表是可行的。
- getClass()用于产生对象的类,并在打印盖雷是,可以看到表示该类类型的编码字符串。
前导 [ 表示这是一个后面紧随的类型的数组,“I”表示基本类型为Int。 - 可变参数列表不依赖于自动包装机之,其实用的是基本类型。
- 可变参数列表于自动包装机制可共处,自动包装机将有选择地将Int参数提升至Integer。
- 可变参数列表是的重载过程变得复杂,在不向方法赋值时,编译器将无法确定调用哪一个方法。
- 添加第二个非可变参数以解决问题。