本文参考了Thinking in Jav
构建器的意义
对于方法的创建,可将其想象成为自己写的每个类都调用一次initialize()。我们在使用对象之前,应首先调用initialize()方法进行初始化,意味着每一用户都能去执行这个方法,但这也意味着用户必须记住调用方法。Java中通过引入构建器,确保每个对象都能得到正确的初始化。若每个类有一个构建器,那么在创建对象时,Java会自动调用那个构建器,确保初始化的进行。
构建器命名规则
l 我们使用的任何名字偶读可能与打算为某个类成员使用的名字冲突
l 编译器的责任需要知道哪个方法是构建器,才能进行调用。
基于以上两个方面,构建器的名字与类名相同。
执行初始化
构建器的名字必须与类名完全相同,所有方法首字母小写的编码规则并不适用于构建器。但是和其他方法一样,构建器也可以使用自变量,以便我们指定对象的具体创建方式。
方法过载
由于构建器的名字由类名决定,所以只能有一个构建器名称。但如果我们需要用多种不同方式来创建一个对象,这时候,就引入了过载的概念。过载简单来说,就是用相同的词表达多种不同的含义。一个类中可以有多个构建器,默认调用无参构造器,如果有传入参数,根据传参的个数和类型匹配调用。方法过载不仅可以用于构建器,也可以用于其他任何方法,且用法非常方便。
class Tree {
int height;
Tree() {
prt("Planting a seedling");
height = 0;
}
Tree( int i) {
prt("Creating new Tree that is" + i +"feet tall");
height = i;
}
void info() {
prt("Tree is "+height+"feet tall");
}
void info(String s) {
prt(s+": Tree is "+height+"feet tall");
}
static void prt (String s){
System.out.println(s);
}
}
public class Overloading {
public static void main(String[] args) {
for (int i = 0; i<5; i++){
Tree t = new Tree(i);
t.info();
t.info("overloaded method");
}
new Tree();
}
}
当然若方法有相同的名字,Java怎么知道我们指的是什么方法呢?这里有一个简单的规则:每个过载的方法都必须采取独一无二的自变量类型列表。
this关键字
this关键字可为已调用了其方法的那个对象生成相应的句柄,且只能在方法内部使用。
比较常用的一个场景是,在构建器里调用构建器。若为一个类写了多个构建器,经常都需要在一个构建器里调用另一个构建器,以避免写重复的代码。可以用this关键字做到这一点。
Static的含义
Static,静态,有点类似于构建了一个全局函数的等价物,我们不能从一个static方法内部发出对非static方法的调用(反过来是可以的)。
清除
Java中有一个垃圾收集器的概念,垃圾收集器可以回收不再使用的对象占据的内存,但是垃圾收集器只知道释放那些由new分配的内存,但是对于那些不是使用new而分配的特殊内存区域,垃圾收集器就无法释放了。为了解决这个问题,Java提供了一个名为finalize()的方法。在理想状态下,一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且在下一次垃圾收集过程中,才会真正回收对象的内存。
最后,我们简单总结一下对象的创建过程,比如一个名为Dog的类
1, 类型为Dog的一个对象首次创建时,或者Dog类的static方法/static字段首次访问时,Java解释器必须找到Dog.class(在事先设好的类路径里搜索)。
2, 找到Dog.class后(它会创建一个Class对象,这将在后面学到),它的所有static初始化模块都会运行。因此,static初始化仅发生一次—在Class对象首次载入的时候。
3, 创建一个new Dog()时,Dog对象的构建进程首先会在内存堆(Heap)里为一个Dog对象分配足够多的存储空间。
4, 这种存储空间会清为零,将Dog中的所有基本类型设为它们的默认值(零用于数据,以及boolean和char的等价设定)
5, 进行字段定义时发生的所有初始化都会执行
6, 执行构建器