11.对象构造【Java温故系列】

参考自–《Java核心技术卷1》


Java 提供了多种编写构造器的机制。


1 重载

有些类有多个构造器,例如:

可以构造一个空的 StringBuilder 对象:

StringBuilder sb1 = new StringBuilder();

也可以指定一个初始字符串构造 StringBuilder 对象:

StringBuilder sb2 = new StringBuilder("To do:\n");

这种特征叫做重载。如果多个方法,有相同的名字、不同的参数,便产生了重载。编译器必须挑选出具体执行哪个方法,它通过用各个方法给出的参数类型与特定方法调用所使用的值类型进行匹配来挑选出相应的方法。如果编译器找不到匹配的参数,就会产生编译时错误,因为根本不存在匹配(或者没有一个比其他的更好),这个过程称为重载解析。

:Java 允许重载任何方法。因此,要完整地描述一个方法,需要指出方法名以及参数类型。这叫做方法的签名。方法的返回类型不是方法签名的一部分,即不能有两个名字相同、参数类型也相同却返回不同类型值的方法。


2 实例域初始化

2.1 构造器初始化实例域

大多数情况下,类的构造器在执行时都会初始化类的实例域。

2.1 默认域初始化

如果在构造器中没有显式地给域赋予初值,那么就会自动地赋予默认值:数值为0、布尔值为 false、对象引用为 null.(包括静态域)

2.2 显式域初始化

通过重载类的构造器方法,可以采用多种形式设置类的实例域的初始状态。确保不管怎样调用构造器,每个实例域都可以被设置为一个有意义的初值。

然而,我们可以在类的定义中,直接将一个值赋给任何域。如:

class Employee{
	private String name = ""; //显式 域初始化
}
//也可以通过调用方法给实例域赋初值

在执行构造器前,先执行赋值操作。当一个类的所有构造器都希望把相同的值赋予某个特定的实例域时,这种方法特别有效。

2.3 初始化块

在一个类的声明中,可以包含多个代码块。只要构造类的对象,这些块就会被执行,如:

public class Employee {
    private static int nextId;

    private int id;
    private String name;
    private double salary;
    
    //静态域初始化(在类的第一次加载时,将会进行静态域的初始化)
    static{
        Random generator = new Rondom();
        //赋予小于1000的任意整数
        nextId = generator.nextInt(1000);
    }
	//代码块(初始化块)
    {
        id = nextId;
        nextId++;
    }

    public Employee(){
        name = "";
        salary = 0;
    }
}

在上述示例中,无论使用哪个构造器构造对象,id 域都在对象初始化块中被初始化。首先运行初始化块,然后才执行构造器的主体部分。(但是不常见,非必需的)


3 构造器

3.1 无参构造器

很多类都包含一个无参数的构造函数,对象由无参数构造函数创建时,其状态会设置为适当的默认值。如:

class Employee{
	private String name;
	private int salary;
	private Data hireDay;
    ...
    public Employee(){
    	//无参构造器,指定默认值
    	name = "";
    	salary = 0;
    	hireDay = LocalDate.now();
    }
}

如果在编写一个类时没有编写构造器,那么系统就会提供一个无参数构造器。这个构造器将所有的实例域设置为默认值。即实例域中的数值型数据域设置为0、布尔型数据域设置为 false、所有对象变量将设置为 null。

如果类中提供了至少一个构造器,但是没有提供无参数的构造器,则在构造对象时如果没有提供参数就会被视为不合法。

3.2 调用另一个构造器

关键字 this 引用方法的隐式参数。然而,这个关键字还有另外一个含义。

如果构造器的第一个语句形如 this(…),这个构造器将调用类的另一个构造器。

public Employee(double s){
	this("Employee #"+nextId,s); //调用Employee(String,double)构造器
	nextId++;
}

如上,调用 new Employee(6000) 时,Employee(double) 构造器将调用 Employee(String,double) 构造器。

采用这种方式使用 this 关键字非常有用,这样对公共的构造器代码部分只编写一次即可。

3.3 调用构造器的具体执行步骤

1)所有数据域被初始化为默认值(0、false、null)

2)按照在类中声明中出现的次序,依次执行所有域初始化语句和初始化块

3)若构造器第一行调用了另外一个构造器,则执行另外那个构造器主体

4)执行这个构造器主体


4 对象析构与 finalize 方法

有些面向对象的程序设计语言,特别是 C++ ,有显示的析构器方法,其中放置一些当对象不再使用时需要执行的清理代码。在析构器中,最常见的操作是回收分配给对象的存储空间。由于 Java 有自动的垃圾回收机制,不需要人工回收内存,所以 Java 不支持析构器。

当然,某些对象可能使用了内存之外的其他资源,如,文件或使用了系统资源的另一个对象的句柄(如 String s;此处 s 就是创建的一个句柄,并不一定有 String 对象与它连接)。这种情况下,当资源不再需要时,将其回收和再利用将显得十分重要。

可以为任何一个类添加 finalize 方法。finalize 方法将在垃圾回收器清除对象之前调用。在实际应用中,不要依赖于使用 finalize 方法回收任何短缺的资源,因为很难知道这个方法在什么时候才能够调用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章