ITEEDU

Java Gossip: 建构方法(Constructor)

在定义类别时,您可以使用「建构方法」(Constructor)来进行对象的初始化,而在Java中并没有 「解构方法」(Destructor),而是利用finalize()函式来达到解构方法的作用,这则在 垃圾回收 讨论。

在Java中建构方法是与类别名称相同的公开方法成员,且没有传回值,例如:

public class SafeArray {
	// ..
	public SafeArray() {?// 建构方法
		// ....
	}
	public SafeArray(参数) {?//
		// ....
	}
}

在建构方法中,您可以定义无参数的建构方法,或具有参数的建构方法,程序在运行时,会根据配置对象时所指定的自变量数据型态等来决定,该使用哪一个建构方法。

下面这个程序中,您实作「安全的数组」,使用我们所定义的数组类别可以动态配置数组长度,并可事先检查存取数组的索引是否超出数组长度,在这个数组类别中,您实作了几个简单的功能,像是传回数组长度、设定数组元素值、取得数组元素值等等,我们的类别定义如下:

SafeArray.java
public class SafeArray {
	private int[] arr;
	public SafeArray() {
		this(10);
	}
	public SafeArray(int length) {
		arr = new int[length];
	}
	public int[] getArray() {
		return arr;
	}
	public int getElement(int i) {
		if(i >= arr.length || i < 0) {
			System.err.println("索引错误");
			return 0;
		}
		return arr[i];
	}
	public int getLength() {
		return arr.length;
	}
	public void setElement(int i, int data) {
		if(i >= arr.length || i < 0) {
			System.err.println("索引错误");
			return;
		}
		arr[i] = data;
	}
}

建构方法中,如果不指定自变量的话,就会预设配置10个元素的数组,您也可以由指定的长度来配置数组;您在无自变量的建构方法中直接使用this() 来呼叫另一个有参数的建构方法,这是一种经常的作法,可以避免撰写一些重复的原始码。

下面这个程序示范如何使用自订的安全数组类别:

UseConstructor.java

public class UseConstructor {
	public static void main(String[] args) {
		// 预设10个元素
		SafeArray arr1 = new SafeArray();?
		// 指定配置20个元素
		SafeArray arr2 = new SafeArray(20);
		for(int i = 0; i < arr1.getLength(); i++)
		arr1.setElement(i, (i+1)*10);
		for(int i = 0; i < arr2.getLength(); i++)
		arr2.setElement(i, (i+1)*10);
		for(int element : arr1.getArray())
		System.out.print(element + " ");
		System.out.println();
		for(int element : arr2.getArray())
		System.out.print(element + " ");
		System.out.println();
	}
}

上面的程序中,您配置了两个SafeArray对象,一个使用预设的建构方法,所以arr1的数组元素会有10个,一个使用指定长度的建构方法,所以arr2的数组元素个 数是我们指定的20,建构方法依自变量不同而自行决定该使用哪一个建构方法。

对象在建构之前,对象的属性必须先初始完毕才会执行建构式,例如:

public class Some {
	private Other other = new Other();
	public Some() {
		System.out.println("Some");
	}
}
public class Other {
	public Other() {
		System.out.println("Other");
	}
}

如果建构Some:

Some some = new Some();

由于先初始Some的属性成员,所以会先显示"Other",再显示"Some"。

如果您如下撰写:

public class Test {
	{
		System.out.println("initial...");
	}
	public Test() {
		System.out.println("Test");
	}
	public Test(int i) {
		System.out.println("Test i");
	}
	public static void main(String[] args) {
		new Test();
		new Test(1);
	}
}

在 { 与 } 之间的程序,会自动加入所有的建构函式开头,所以程序将显示:

initial...
Test
initial...
Test i