4: Initialization & Cleanup(初始化与清理)

用构造函数确保初始化
注意,编程风格要求的方法的首字母要小写的要求不适用于构造函数,因为构造函数的名字必须与类的名字完全相同。
构造函数是一种特殊的方法,它没有返回值。这一点同void型的方法有着本质上的区别,void型的方法什么都不返回,但这是你决定的,你也可以让它返回些什么。而构造函数则什么都不返回,而且你别无选择(new表达式确实会返会返回这个新创建的对象的reference,但是构造函数本身不返回任何值)。如果构造函数能有返回值,而且你还可以选择这个值,那么编译器就要问了,它应该怎样处置这个返回值。

方法的重载
区分经过重载的方法
即使是参数顺序的颠倒也足以将两个方法区分开来。(不过,通常情况下别用这种办法,因为这会产生难以维护的代码。)
对primitive进行重载
如果实参(真正调用方法的那个参数)的类型比形参(方法的定义中所声明的参数)的类型小,那么数据会先提升。
如果你传的参数比它大,那么你就只能把它转换成这个类型的值。把类型的名字放在括号里就行了。不这么做,编译器就会报错。
用返回值重载
调用方法的时候是可以忽略返回值的。由于你并不关心方法调用所返回的值,而只想利用其副作用,因此这通常被称为“为利用其副方法而调用方法(calling a method for its side effect)”。因此,不能用返回值来区分重载的方法。
默认的构造函数
如果你写了一个没有构造函数的类,那么编译器会自动为你创建一个默认的构造函数。但是,只要定义了构造函数(不管带不带参数),编译器就不会再自动合成默认的构造函数了。
this关键词
this关键词只能用于方法内部,它负责返回调用这个方法的对象的reference。记住,如果你想在别的类的方法里调这个类的方法,那么无须使用this,直接调用就是了。当前对象的this会自动地用于其它方法。this只应用于那些,你明确指明要使用对象的reference的特殊情况。
在构造函数里调用构造函数
可以用this调用一个构造函数,但是不能调用两个。此外,你还得在程序的最前面调用构造函数,否则编译器就会报错。
参数s的名字和类的数据成员s的名字相同,于是就产生了二义性。你可以用this.s来解决这个问题。它表示你要用类的数据成员。
编译器不会让你在方法里调用构造函数,除非它自己就是构造函数。
static的含义
类的static方法只能访问其它static方法和static数据成员。
static方法有全局函数的意思,因此它不是面向对象的;你不能用static方法向对象发消息,因为它没有this。如果你发现用了很多static方法,那么你大概得重新思考一下你的设计策略了。

清理:finalization和垃圾回收
1. 对象不一定会被垃圾回收器回收。
2. 垃圾回收不是拆构(destruction)。
为什么要有finalize()?
3. 垃圾回收只与内存有关。
不论对象是以什么方式创建的,内存释放都是由垃圾回收器负责的。只有在一些非常特殊的场合才会需要用到finalize(),这种场合就是内存是以创建对象以外的形式被分配给对象时。
你必须亲自进行清理
记住,垃圾回收和finalize()都是靠不住的。只要JVM还没到快要耗尽内存的地步,它是不会浪费时间来回收垃圾以恢复内存的。
中止条件
垃圾回收器是如何工作的

自适应的,分代的,停止和拷贝,标识和清扫。

成员的初始化
如果变量是在方法内部定义的局部变量,这种保障就表现为编译时的错误信息。
指定初始化
用构造函数进行初始化
你并没有排除自动的初始化,它在构造函数运行之前就已经完成了。
初始化的顺序
变量的定义可能分散在类定义的各个地方,并且与方法的定义相互交错,但是变量的初始化会先于任何方法,甚至是构造函数的调用。
静态数据的初始化
只有创建了第一个对象之后(或者第一次访问static成员的时候),它们才会被初始化。此后,static对象就不会再作初始化了。如果先前没有创建过这种对象,因而其static的成员尚未初始化的话,初始化会先处理其static成员,再处理非static的对象。
1. 第一次创建Dog类的对象(构造函数实际上是static方法),或者第一次,访问Dog类的static的方法或字段的时候,Java解释器会要搜寻classpath,找到Dog.class。
2. 装载了Dog.class之后(创建了Class对象之后),会对所有的static数据进行初始化。这样第一个装载 Class对象的时候,会先进行static成员的初始化。
3. 用new Dog()创建新对象的时候,Dog对象的构建进程会先在堆里为对象分配足够的内存。
4. 这块内存先被清零,这样就自动地把Dog对象的primitive类型的成员赋上缺省的值(对于数字就是零,或者是相应的boolean和char),将reference设成null。
5. 执行定义成员数据时所作的初始化。
6. 执行构造函数。这可能会牵涉到相当多的活动,特别时有继承的时候。
显式的静态初始化
非静态的实例初始化

这种语法为匿名内部类(anonymous inner class)的初始化提供了必不可少的支持。

数组的初始化
多维数据

总结

练习

「读书笔记」Thinking in Java 3rd Edition - 5: Hiding the Implementation