成员初始化
- 局部变量如果未初始化则会编译时抛出异常
void f(){
int i;
i++;
}
- 要是类的数据成员是基本类型,那么就会有一个初始值。如果类的数据成员是一个对象的话,默认初始值是 null。
public class ApiTestDaoTest{
boolean t;
char c;
byte b;
short s;
int i;
long l;
double d;
float f;
ApiTestDaoTest reference;
Integer Int;
@Test
public void printInitialValues(){
System.out.println("data type initial value ");
System.out.println("boolean "+ t);
System.out.println("char "+c);
System.out.println("byte "+b);
System.out.println("int "+i);
System.out.println("short "+s);
System.out.println("long "+l);
System.out.println("float "+f);
System.out.println("double "+d);
System.out.println("reference " + reference);
System.out.println("Integer " + Int);
}
}
data type initial value
boolean false
char
byte 0
int 0
short 0
long 0
float 0.0
double 0.0
reference null
Integer null
构造器初始化
构造器来进行初始化,是为了在运行时刻,可以调用方法或执行某些动作来确定初始值。
初始化顺序
- 在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法中,他们仍然会在任何方法(包括构造器)被调用之前得到初始化:
class Window{
Window(int marker){
System.out.println("Window marker == "+marker);
}
}
class House{
Window w1 = new Window(1);
House(){
System.out.println("House()");
w3 = new Window(33);
}
Window w2 = new Window(2);
void f(){
System.out.println("f()");
}
Window w3 = new Window(3);
}
House h = new House();
h.f();
由输出可见,w3 这个引用会被初始化2次。一次是在作为 House 的初始值,一次是House 的构造器中(第一次的引用对象将被丢弃,并作为垃圾回收)。
5.7.2 静态数据的初始化
无论创建多少个对象,静态数据都只占用一份存储空间。static 关键字不能应用于局部变量,因此它只能作用于域。如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就会获得基本类型的标准初值;如果它是一个对象引用,那么它的默认初始值就是null。
// static 不能用于局部变量。static 可以定义一个方法或者属性,但是不能定义一个方法内的一个变量,如下:
void a(){
static int a = 3; // 会报错
}
如果想在定义处进行初始化,采取的方法与非静态数据没什么不同。
初始化的顺序是先静态对象,后是 “非静态” 对象。——这块没太整明白。
- 即使没有显示地使用 static 关键字,构造器实际上也是静态方法。假设有个 Dog 类,当首次创建类型为 Dog 的对象时或者 Dog 类的静态方法/静态域首次被访问时,Java 解释器必须查找类路径,以定位 Dog.class 文件。
- 然后载入 Dog.class (这将创建一个 Class 对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在 Class 对象首次加载的时候进行一次。
- 当用 new Dog() 创建对象时,首先将在堆上为 Dog 对象分配足够的存储空间。
- 分配的这块存储空间上,Dog 所有的基本类型数据都设置了默认值,而引用则被设置为了 null。
- 执行所有出现于字段定义处的初始化动作
- 执行构造器
显式的静态初始化
Java 允许将多个静态初始化动作组织成一个特殊的 “静态子句”:
public class Spoon{
static int i;
static {
i = 47;
}
}
这段静态代码块也仅执行一次。当首次生成这个类的一个对象时,或者首次访问属于这个静态代码块的数据成员时,这段静态代码块会执行一次。
非静态实例初始化
Java 中也有被称为实例初始化的类似语法,用来初始化每一个对象的非静态变量。
{
int i = 0;
int a = 1;
}
数组初始化
数组是类型相同的、用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。数组是通过方括号下标操作符[] 来定义的,要定义一个数组,只需要在类型名后加上一对空方括号即可;
编译器不允许指定数组的大小。现在拥有的只是对数组的一个引用(你已经为该引用分配了足够多的存储空间),而且也没给数组对象本身分配任何空间。为了给数组创建相应的存储空间,必须写初始化表达式。对于数组,初始化动作可以出现代码的任何地方,但也可以使用一种特殊的初始化表达式,它必须在创建数组的地方出现。这种特殊的初始化是由一对花括号括起来的值组成的。在这种情况下,存储空间的分配(等价于使用 new)将由编译器负责,
int[] a1 = {1,2,3,4};
int a2 = a1;
,这个操作只是复制的一个引用:
@Test
public void printInitialValues(){
int[] a1 = {1,2,3,4};
int[] a2;
a2 = a1;
for(int i=0;i<a2.length;i++){
a2[i] = a2[i] + 1;
}
for(int i : a1){
System.out.println(i);
}
}
// 2 3 4 5
由此可见,a1 和 a2 只是同一个数组的引用的不同别名。