5.1 用构造器确保初始化
1)构造器采用与类名相同的名称。由于构造器的名称必须与类名完全相同,所以“每个方法首字母小写”的编码风格并不适用于构造器。
2)构造器可以带有形式参数,也可以不接受任何参数。不接收任何参数的构造器叫做默认构造器。
3)构造器是一种特殊类型的方法,因为它没有返回值,这与返回值为空(void)明显不同。
5.2 方法重载
1)为了让方法名相同而形式参数不同的构造器同时存在,必须用到方法重载。
5.2.1 区分重载方法
1)每个重载的方法多必须有一个独一无二的参数类型列表,可以是方法的参数个数不同、参数的类型不同、或者二者都不同。
2) 参数顺序的不同也足以区分两个方法,不过一般情况下别这么做,这会是代码难以维护。
eg: static void f(int i,String s) 和 static void f(String s,int i) 这两个方法。
5.2.2 涉及基本类型的重载
1)基本类型能够从一个“较小”的类型自动提升至一个“较大”的类型,此过程一单牵涉到重载,可能会造成一些混淆。
5.2.3 以返回值区分重载方法
1)不能根据返回值不同来区分重载方法。
eg:void f() {} 与 int f() { return 1; } 这两个方法,你可能会调用方法而忽略其返回值,所以当你像下面这样调用方法:
f();
此时Java如何才能判断应该调用哪一个f()呢?因此,根据方法的返回值来区分重载方法是行不通的。
5.3 默认构造器
1)默认构造器(又名“无参构造器”)是没有形式参数的---它的作用是创建一个“默认对象”。如果你写的类中没有构造器,则编译器会自动帮你创建一个默认构造器。
2)如果你已经定义了一个构造器(无论有无参数),编译器都不会帮你自动创建默认构造器。
5.4 this关键字
1)this 关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。
5.4.1 在构造器中调用构造器
1)可能为一个类谢了多个构造器,又是可能想在一个构造器中调用另一个构造器以避免重复代码,可用this关键字做到这一点。
2)通常写this的时候,都是指“这个对象”或者“当前对象”,而且它本身表示对当前对象的引用。
3)当方法的参数与类的数据成员的名字相同时,使用this.作为前缀能够代表类的数据成员。
5.4.2 static的含义
1)static方法就是没有this的方法,在static方法的内部不能调用非静态方法,非静态方法则可以调用静态方法。
2)可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。
5.5 清理:终结处理和垃圾回收
1)对象可能不被垃圾回收。
2)垃圾回收并不等于“析构”。
5.5.1 finalize() 的用途何在
3)垃圾回收治愈内存有关。
5.5.2 你必须实施清理
1)无论是“垃圾回收”还是“终结”,都不保证一定会发生,如果Java虚拟机并未面临内存耗尽的庆幸,他是不会浪费时间去执行垃圾回收以回复内存的。
5.5.3 终结条件
1)当对某个对象不在感兴趣———也就是它可以被清理了,这个对象应该处于某种状态,使它占用的内存可以被安全的释放。
5.5.4 垃圾回收器如何工作
1)垃圾回收器对于提高对象的创建速度,具有明显的效果。
2)引用计数法是一种简单但速度很慢的垃圾回收技术。
3)停止-复制:先暂停程序的运行(所以它不属于后台回收模式),然后将所有存活的对象从当前堆复制到另一个堆,没有被复制的全部都是垃圾。
4)标记-清扫:遍历所有的引用,进而找出所有存活的对象,每当它找到一个存活对象,就会给对象设一个标记,这个过程中不会回收任何对象,只有全部标记工作完成的时候,清理工作才会开始。
5)Java虚拟机综合使用以上多种垃圾回收方式,可以称之为“自适应的、分代的、停止-复制、标记-清扫”式垃圾回收器。
5.6 成员初始化
1)类的每个基本类型成员保证都会有一个初始值。
2)在类中定义一个对象引用时,如果不将其初始化,次饮用就会获得一个特殊值null。
5.6.1 指定初始化
1)如果想给某个变量赋初值,就在定义类成员变量的地方为其赋值(注意在C++ 里不能这样做)。
2)初始化有顺序限制。
5.7 构造器初始化
1)可以使用构造器来进行初始化,在运行时刻,可以调用方法或者执行某些动作来确定初值。
2)无法阻止自动初始化的进行,它将在构造器被调用之前发生。
5.7.1 初始化顺序
1)在类的内部,变量定义的先后顺序决定了初始化的顺序,即使变量定义散布于方法定义之间,他们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
5.7.2 静态数据的初始化
1)无论创建多少个对象,静态数据都只占用一份存储区域。
2)static关键字不能应用于局部变量,因此它只能作用于域。
3)如果一个域是静态的基本类型域,且也没有对他进行初始化,那么它就会获得基本类型的标准初值,如果它是一个对象引用,那么它的默认初始化值就是null;
4)初始化的顺序是先静态对象(如果它们未因前面的对象创建过程而被初始化),后面是“非静态”对象。
5)总结一下对象的创建过程,假设有个名为Dog的类:
1. 即使没有显示的使用static关键字,构造器实际上也是静态方法,因此,当首次创建类型为Dog的对象是(构造器可以堪称静态方法),或者Dog类的静态方法/静态域首次北方问是Java解释器必须查找类路径,以定位Dog.class文件。
2. 然后载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作都会执行,因此静态初始化只在Class对象首次加载的时候进行一次。
3. 当用new Dog() 床架对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
4. 这块存储空间会被清零,这就自动的将Dog对象中的所有基本类型数据都设置成了默认值,而引用呢呗设置成null。
5. 执行所有出现于字段定义处的初始化动作。
6. 执行构造器。
5.7.3 显示的静态初始化
1)Java允许将多个静态初始化组织称一个特殊的“静态字句”(有时也叫做“静态块”),就像下面这样:
public class Spoon {
static int i;
static {
i = 47;
}
}
2)这段代码仅执行一次,当首次生成这个类的一个对象时,或者首次访问属于哪个类的静态数据成员时(即便从未生成这个类的对象)。
5.7.4 非静态实例初始化
1)Java中也有被称为实例初始化的类似于静态代码块的语法,用来初始化每一个对象的非静态变量。
2)它的语法与静态初始化字句一模一样,只不过少了static关键字。
3)实例初始化字句是在构造器执行之前执行。
5.8 数组初始化
1)数组知识相同类型的、用一个标识符名称封装到一起的一个对象序列或者基本类型数据序列。
2)所有数组都有一个故友成员,可以通过它获知数组内包含了多少铬元素,但不能对其进行修改,这个成员就是length.
注:数组没有length()方法,只有length属性,String有length()方法,但是没有length属性。
3)数组的创建是在运行时刻执行的。
4)数组元素中的基本数据类型值会被初始化成空值(对于数字和字符,就是0; 对于布尔型,是false)。
5.8.1 可变参数列表
1)在Java SE5之前能够使用下面的方法来实现方法的可变参数列表:
//该方式利用了所有的类都直接或间接继承与Object类
//所以可以创建以Object数组为参数的方法实现可变参数
static void printArray(Object[] args) { /* 对参数数组的操作 */}
2)Java SE5之后添加了新的特性用于实现可变参数列表,如下:
//java SE5新增的特性
static void printArray(Object... args){/* 对参数的操作 */}
3)可以将0个参数传递给可变参数列表。
4)在可变参数列表中可以使用任何类型的参数,包括基本类型。
5.9 枚举类型
1)在Java SE5中添加了一个新的小特性,即enum关键字,它使我们在需要群组并使用美剧类型集时,可以很方便的处理。
2)enum是一个特别实用的特性,即它可以在switch语句内使用。
总结,本章作者主要讲述对象初始化过程和垃圾回收机制,由于原文篇幅过大不能很好的理解这些内容,这里我推荐看看 骆昊 老师的总结,传送门:Java面试题全集(上) ,第二十一条:JVM加载class文件的原理机制 和 第三十条 GC是什么 的内容。