导语:java尽力保证所有变量在使用前都能得到恰当的初始化
1.成员变量初始化
- 局部方法中的局部变量:Java以编译时错误的形式来贯彻这种保证。如果局部变量没有初始化,那么就会得到一条错误或警告的提示。
当然,编译器也可以为i赋一个默认值,但是未初始的局部变量更有可能是程序员的疏忽,所以采用默认值初始化反而会掩盖这种失误。 - 类的数据成员(字段)是基本类型:每个数据成员都会保证有一个初始值。
- 在类中定义一个对象引用,如果不将其初始化,此引用就会获得一个特殊值null.
2.构造器的初始化
- 无法阻止自动初始化(默认值)的进行,它将在构造器被调用之前发生。可以在构造器中来确定初值。
public class test { int i; public test() { i = 1; } }
i将先被默认初始化为0,然后在调用构造器是变成7,初始化早已得到了保证。
3.初始化的顺序
- 在类的内部,变量定义的先后决定了初始化的顺序,即使变量定义散乱在方法定义之间,也保证在方法调用之前得到初始化。
4.静态数据的初始化
- 无论创建多少个对象,静态数据都只占用一份存储区域。static关键字不能用于局部变量,因此它只作用于域。
- 如果一个域是静态的基本类型域,且也没有对他进行初始化,那么它就会获得基本类型的标准初值,
如果是一个引用,那默认值就是null。 - 初始化的顺序是先静态对象,然后是“非静态”的。
- 静态初始化只有在Class对象首次加载的时候进行一次。
5.显式的静态初始化
- java允许将多个静态初始化动作组织成一个特殊的“静态子句”(也可称为静态块),
static int i; static{ i = 49; }
这段代码仅执行一次:当首次生成这个类的一个对象时,或首次方位属于这个类的静态成员时执行一次。
6.非静态实例的初始化
- 用来初始化每一个对象的非静态变量、
这种语法对于支持“匿名内部类”的初始化时必须的,可以保证无论调用了那个显示构造器,某些操作都会发生。在调用构造器之前发生。public class test { int i; { i = 49; } }
7.数组初始化
- 数组只是相同类型的、用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。
- 数组本身就是一个对象
- 编译器不允许制定数组的大小
- 给数组分配存储空间,必须写初始化表达式,初始化可以发生在任何地方
- 一种特殊的初始化表达式。由一堆花括号括起来的值组成(等价于new),存储空间的分配由编译器负责。
- 用length获取数组中有多少个元素。
- int[] a = new int[rand.nextInt(20)]; 数组中元素会自动初始化值,如int型的就会全部初始化为0.[0,0,0,0,0,·······]
- 初始化的最后一个,号是可选的
8.可变参数列表
- 就是一个数组;如下
public class test { private void printArray(String... strings){ //strings 就是一个数组 for (int i = 0; i < strings.length; i++) { System.out.println(strings[i]); } } public static void main(String[] args) { new test().printArray("呵呵","哈哈","嘻嘻"); } }
当指定参数时,编译器会为你填充数组。获取到的仍旧是一个数组。 - 可变参数列表和自动包装机制
public class test { private void printArray(String... strings){ //strings 就是一个数组 for (int i = 0; i < strings.length; i++) { System.out.println(strings[i]); } } public static void main(String[] args) { new test().printArray("呵呵","哈哈","嘻嘻",new String("哦")); } }
总结
- 构造器能保证正确的初始化和清理。
- 没有正确的构造器调用,编译器就不允许创建对象。
- 在不需要类似析构的情况下,垃圾回收器会简化编程工作,处理内存的时候也更安全。