對象和簡單數據對象
這節教程將開始討論對象的生命周期。包括怎樣創建對象、怎樣使用它以及在不使用它的時候將它從系統中清除。下面一個一個介紹:
4.1 對象的生命周期
在這一小節中你可以學到怎樣創建和使用任何類型的對象,還討論了當對象不再需要的時候系統怎樣清除對象的。
典型的JAVA程序創建對象,對象之間的交互是通過發送消息來實現的。通過這些對象的交互,Java程序可以執行一個GUI、運行一個動畫或者通過網絡發送和接收信息。一旦對象已經完成了任務,它就被作為無用信息被回收,它的資源可以由其它對象回收利用。
以下是一個小的例子程CreateObjectDemo,它創建三個對象:一個是Point對象和兩個Rectange對象,你需要這三個源程序才可以編譯這個程序:
public class CreateObjectDemo {
public static void main(String[] args) {
//創建一個Point對象和兩個Rectangle對象
Point origin_one = new Point(23, 94);
Rectangle rect_one = new Rectangle(origin_one, 100, 200);
Rectangle rect_two = new Rectangle(50, 100);
// 顯示rect_one的寬、高以及面積
System.out.println("Width of rect_one: " + rect_one.width);
System.out.println("Height of rect_one: " + rect_one.height);
System.out.println("Area of rect_one: " + rect_one.area());
// 設置rect_two的位置
rect_two.origin = origin_one;
// 顯示rect_two的位置
System.out.println("X Position of rect_two: " + rect_two.origin.x);
System.out.println("Y Position of rect_two: " + rect_two.origin.y);
// 移動rect_two並且顯示它的新位置
rect_two.move(40, 72);
System.out.println("X Position of rect_two: " + rect_two.origin.x);
System.out.println("Y Position of rect_two: " + rect_two.origin.y);
}
}
一旦創建了對象,程序就可以操作對象並將它們有關的一些信息顯示出來,以下是這個程序的輸出結果:
Width of rect_one: 100
Height of rect_one: 200
Area of rect_one: 20000
X Position of rect_two: 23
Y Position of rect_two: 94
X Position of rect_two: 40
Y Position of rect_two: 72
這一節使用這個例子來在程序中描述對象的生命周期。從這你可以學到怎樣編寫代碼來創建、使用對象以及系統怎樣將它從內存中清除的。
下面主要分成幾部分來討論:
創建對象
使用對象
清除沒有使用的對象
4.1.1 創建對象
眾所周知,可以從類來創建對象。下面的幾條語句都是用來創建對象的,它們都是來自上面程序CreateObjectDemo程序:
Point origin_one = new Point(23, 94);
Rectangle rect_one = new Rectangle(origin_one, 100, 200);
Rectangle rect_two = new Rectangle(50, 100);
上面第一條語句從Point類創建了一個對象,而第二條和第三條語句是從Rectangle類眾創建了對象。但是每條語句都有三部分組成:
聲明:Point origin_one、Rectangle rect_one以及Rectangle rect_two都是變量的聲明,它們的格式是類型後加變量名。當你創建一個對象的時候,你不必聲明一個變量來引用它。然而,變量生命經常出現在創建對象代碼的相同行上。
實例化:new是Java運算符,它可以創建新的對象並且為對象分配了內存空間。
初始化:new運算符後跟著一個構造函數的調用。比如 Point(23,94)就是一個Point類的構造函數的調用。這個構造函數初始化了這個新對象。
4.1.1.1 聲明一個變量來引用對象
從前面的教程,你應該知道了如何聲明一個變量了,你可以這樣來編寫:
type name
其中type是數據類型,而name是變量名。
除了原始類型(比如int和boolean),Java平台還直接提供了類和接口也是數據類型。這樣為了聲明一個變量來引用對象,你可以使用類或者接口的名字作為變量的類型。下面的例程使用了Point和Rectangle類作為類型來聲明變量:
Point origin_one = new Point(23, 94);
Rectangle rect_one = new Rectangle(origin_one, 100, 200);
Rectangle rect_two = new Rectangle(50, 100);
聲明沒有創建新對象。Point origin_one代碼沒有一個新的Point對象,它只是聲明一個變量orgin_one,它將用來引用Point對象。這個引用暫時是空的直到被賦值了。一個空的引用就是一個NULL引用。
4.1.1.2 實例化對象
為了創建一個對象你必須用new來實例化它。New運算符是通過為新對象分配內存來實例化一個類的。這個new運算符需要一個後綴參數,即構造函數的一個調用。構造函數的名字提供了要初始化類的名字。構造函數初始化了新的對象。
New運算符號返回一個引用給它創建的對象的。通常,這個引用被賦值為適當類型的變量。
4.1.1.3 初始化對象
以下是Point類的代碼:
public class Point {
public int x = 0;
public int y = 0;
//一個構造函數
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
這個類包含了一個構造函數。你可以識別這個構造函數因為它跟類的名字是相同名字的,它沒有任何的返回類型。這個在Point類中的構造函數有兩個整型參數,它是由代碼(int x, int y)來定義的。下面的整數23和94就是這個參數的數值:
Point origin_one = new Point(23, 94);
4.1.1.3 初始化對象
下面是Rectangle類的代碼,它包含了四個構造函數:
public class Rectangle {
public int width = 0;
public int height = 0;
public Point origin;
//四個構造函數
public Rectangle() {
origin = new Point(0, 0);
}
public Rectangle(Point p) {
origin = p;
}
public Rectangle(int w, int h) {
this(new Point(0, 0), w, h);
}
public Rectangle(Point p, int w, int h) {
origin = p;
width = w;
height = h;
}
//用於移動rectangle的方法
public void move(int x, int y) {
origin.x = x;
origin.y = y;
}
//用於計算矩形面積的方法
public int area() {
return width * height;
}
}
每一個構造函數可以讓你為矩形的各個方法提供初始數值,你可以設置矩形的原點、寬度和高度。如果一個類中有多個構造函數,它們的名字都是相同的只是它們有不同類型的參數或者不同數目的參數。JAVA平台可以根據參數的不同數目和類型類來區分構造函數。當Java平台遇到的代碼的時候,它就調用在Rectangle類中的構造函數,這個函數需要一個Point參數以及兩個整型參數:
Rectangle rect_one = new Rectangle(origin_one, 100, 200);
這個調用初始化了矩形的原點(orgin_one)。代碼也設置了矩形的寬度(100)和高度(200)。
多個引用可以引用相同的對象。下面的代碼行調用了需要兩個整型參數的構造函數,它為寬度和高度提供了初始化數值。如果你仔細看看這個代碼,你會發現它創建一個Point對象,它的x和y數值被初始化為0。
下面的Rectangle構造函數沒有任何參數:
Rectangle rect = new Rectangle();
如果一個類沒有顯性聲明任何構造函數,Java平台自動提供一個沒有參數的構造函數,這是一個缺省的構造函數,它沒有完成任何事情。這樣,所有的類就至少有一個構造函數。
4.1.2 使用對象
一旦你創建了一個對象,你可能想使用它來做一些事情。你可能從它得到一些信息,或者想改變它的狀態或者讓它來完成一些動作。對象允許你做以下兩件事情:
操作或者檢查它的變量。
調用它的方法。
4.1.2.1 引用對象的變量
下面是引用對象變量的基本形式,它是使用了有條件的名字即長名字:
objectReference.variableName
當實例變量處在作用域內的時候,你可以為實例變量使用一個簡單的名字,也就是說,在對象類的代碼中。處在對象類外面的代碼必須使用有條件的名字。比如,在CreateObjectDemo類中的代碼處在類Rectangle類代碼的外面。所以為了引用Rectangle對象rect_one的origin、width和height變量,CreateObjectDemo必須相應使用rect_one.origin、rect_one.width和rect_one.height。這個程序使用了rect_one的width和height:
System.out.println("Width of rect_one: " + rect_one.width);
System.out.println("Height of rect_one: " + rect_one.height);
如果直接使用在CreateObjectDemo類中的變量width和height,那就將產生一個編譯錯誤。在後面,程序還將使用類似的代碼來顯示關於rect_two的信息。相同類型的對象將有相同實例變量的副本。這樣,每一個Rectangle對象就都有變量origin、width和height了。當你通過對象引用來訪問實例變量的時候,你就引用了特定對象的變量。在CreateObjectDemo程序有兩個對象rect_one和rect_two,它們有不同的origin、width和height變量:
對象的長文件名的第一部分是對象引用,它必須是一個對象的引用。這裡你可以使用引用變量的名字,或者你可以使用任何的表達式來返回一個對象引用。重新調用這個new運算符可以返回一個對象的引用。這樣你可以使用從new返回的數值來訪問一個新的對象變量:
int height = new Rectangle().height;
這個語句創建了一個新的Rectangl