典型的Java程序會建立許多對象,如你所知,經過調用方法進行交互,經過這些對象交互,程序能夠執行各類任務,例如實現GUI,運行動畫或經過網絡發送和接收信息,一旦對象完成了建立它的工做,它的資源就會被回收以供其餘對象使用。小程序
這是一個名爲CreateObjectDemo
的小程序,它建立了三個對象:一個Point
對象和兩個Rectangle
對象,你將須要全部三個源文件來編譯此程序。segmentfault
public class CreateObjectDemo { public static void main(String[] args) { // Declare and create a point object and two rectangle objects. Point originOne = new Point(23, 94); Rectangle rectOne = new Rectangle(originOne, 100, 200); Rectangle rectTwo = new Rectangle(50, 100); // display rectOne's width, height, and area System.out.println("Width of rectOne: " + rectOne.width); System.out.println("Height of rectOne: " + rectOne.height); System.out.println("Area of rectOne: " + rectOne.getArea()); // set rectTwo's position rectTwo.origin = originOne; // display rectTwo's position System.out.println("X Position of rectTwo: " + rectTwo.origin.x); System.out.println("Y Position of rectTwo: " + rectTwo.origin.y); // move rectTwo and display its new position rectTwo.move(40, 72); System.out.println("X Position of rectTwo: " + rectTwo.origin.x); System.out.println("Y Position of rectTwo: " + rectTwo.origin.y); } }
該程序建立、操做和顯示有關各類對象的信息,這是輸出:網絡
Width of rectOne: 100 Height of rectOne: 200 Area of rectOne: 20000 X Position of rectTwo: 23 Y Position of rectTwo: 94 X Position of rectTwo: 40 Y Position of rectTwo: 72
如下三節使用上面的示例來描述程序中對象的生命週期,經過它們,你將學習如何編寫在你本身的程序中建立和使用對象的代碼,你還將瞭解系統在對象生命結束後如何清理。函數
如你所知,一個類提供了對象的藍圖;你從一個類建立一個對象,從CreateObjectDemo
程序獲取的如下每一個語句都會建立一個對象並將其分配給變量:學習
Point originOne = new Point(23, 94); Rectangle rectOne = new Rectangle(originOne, 100, 200); Rectangle rectTwo = new Rectangle(50, 100);
第一行建立Point
類的對象,第二行和第三行分別建立Rectangle
類的對象。動畫
這些語句中的每個都有三個部分(下面將詳細討論):spa
new
關鍵字是一個建立對象的Java運算符。new
運算符後面是對構造函數的調用,該構造函數初始化新對象。以前,你瞭解到要聲明變量,你能夠編寫:code
type name;
這會通知編譯器你將使用name
來引用類型爲type
的數據,對於原始變量,此聲明還爲變量保留適當的內存量。對象
你還能夠在本身的代碼行上聲明引用變量,例如:blog
Point originOne;
若是你像這樣聲明originOne
,它的值將不肯定,直到實際建立並分配了一個對象,簡單地聲明引用變量不會建立對象,爲此,你須要使用new
運算符,以下一節所述,在代碼中使用對象以前,必須將對象分配給originOne
,不然,你將收到編譯器錯誤。
此狀態中的變量(當前不引用任何對象)能夠以下所示(變量名稱,originOne
,以及指向無的引用):
new
運算符經過爲新對象分配內存並返回對該內存的引用來實例化一個類,new運算符還調用對象構造函數。
注意:短語「實例化類」與「建立對象」的含義相同,建立對象時,你正在建立類的「實例」,所以「實例化」一個類。
new
運算符須要一個後綴參數:對構造函數的調用,構造函數的名稱提供要實例化的類的名稱。
new
運算符返回對其建立的對象的引用,此引用一般分配給適當類型的變量,如:
Point originOne = new Point(23, 94);
new
運算符返回的引用沒必要分配給變量,它也能夠直接用在表達式中,例如:
int height = new Rectangle().height;
這條語句將在下一節中討論。
這是Point
類的代碼:
public class Point { public int x = 0; public int y = 0; //constructor public Point(int a, int b) { x = a; y = b; } }
該類包含一個構造函數,你能夠識別構造函數,由於它的聲明使用與該類相同的名稱,而且它沒有返回類型,Point
類中的構造函數接受兩個整數參數,由代碼(int a, int b)
聲明,如下語句提供23
和94
做爲這些參數的值:
Point originOne = new Point(23, 94);
執行此語句的結果能夠在下圖中說明:
這是Rectangle
類的代碼,它包含四個構造函數:
public class Rectangle { public int width = 0; public int height = 0; public Point origin; // four constructors public Rectangle() { origin = new Point(0, 0); } public Rectangle(Point p) { origin = p; } public Rectangle(int w, int h) { origin = new Point(0, 0); width = w; height = h; } public Rectangle(Point p, int w, int h) { origin = p; width = w; height = h; } // a method for moving the rectangle public void move(int x, int y) { origin.x = x; origin.y = y; } // a method for computing the area of the rectangle public int getArea() { return width * height; } }
每一個構造函數都容許你使用基本類型和引用類型爲矩形的origin
、width
和height
提供初始值,若是一個類有多個構造函數,則它們必須具備不一樣的簽名,Java編譯器根據參數的數量和類型區分構造函數。當Java編譯器遇到如下代碼時,它知道在Rectangle
類中調用構造函數,該構造函數須要一個Point
參數後跟兩個整數參數:
Rectangle rectOne = new Rectangle(originOne, 100, 200);
這就要求Rectangle
的一個構造初始化原點originOne
,此外,構造函數將width
設置爲100
,將height
設置爲200
,如今有兩個對同一個Point
對象的引用 — 一個對象能夠有多個對它的引用,以下圖所示:
如下代碼行調用Rectangle
構造函數,該構造函數須要兩個整數參數,這些參數提供width
和height
的初始值,若是檢查構造函數中的代碼,你將看到它建立了一個新的Point
對象,其x
和y
值初始化爲0
:
Rectangle rectTwo = new Rectangle(50, 100);
如下語句中使用的Rectangle
構造函數不帶任何參數,所以它被稱爲無參數構造函數:
Rectangle rect = new Rectangle();
全部類至少有一個構造函數,若是類沒有顯式聲明任何,則Java編譯器會自動提供一個無參數構造函數,稱爲默認構造函數。此默認構造函數調用父類的無參數構造函數,若是類沒有其餘父級,則調用Object
構造函數,若是父級沒有構造函數(Object
確實有構造函數),編譯器將拒絕該程序。
一旦你建立了一個對象,你可能想要用它來作某事,你可能須要使用其中一個字段的值,更改其中一個字段,或調用其中一個方法來執行操做。
對象字段按名稱訪問,你必須使用明確的名稱。
你能夠在其本身的類中對於字段使用簡單名稱,例如,咱們能夠在Rectangle
類中添加一個打印width
和height
的語句:
System.out.println("Width and height are: " + width + ", " + height);
在這種狀況下,width
和height
是簡單的名稱。
對象類外部的代碼必須使用對象引用或表達式,後跟點(.
)運算符,後跟簡單字段名稱,以下所示:
objectReference.fieldName
例如,CreateObjectDemo
類中的代碼位於Rectangle
類的代碼以外,所以,要引用名爲rectOne
的Rectangle
對象中的origin
、width
和height
字段,CreateObjectDemo
類必須分別使用名稱rectOne.origin
、rectOne.width
和rectOne.height
,該程序使用其中兩個名稱來顯示rectOne
的width
和height
:
System.out.println("Width of rectOne: " + rectOne.width); System.out.println("Height of rectOne: " + rectOne.height);
嘗試在CreateObjectDemo
類中的代碼使用簡單名稱的width
和height
沒有意義 — 這些字段僅存在於對象中 — 並致使編譯器錯誤。
稍後,該程序使用相似的代碼來顯示有關rectTwo
的信息,相同類型的對象具備本身的相同實例字段的副本,所以,每一個Rectangle
對象都有名爲origin
、width
和height
的字段。經過對象引用訪問實例字段時,將引用該特定對象的字段,CreateObjectDemo
程序中的兩個對象rectOne
和rectTwo
具備不一樣的origin
、width
和height
字段。
要訪問字段,你可使用對象的命名引用,如前面的示例所示,或者你可使用任何返回對象引用的表達式。回想一下,new
運算符返回對象的引用,所以,你可使用new
返回的值來訪問新對象的字段:
int height = new Rectangle().height;
該語句建立一個新的Rectangle
對象並當即得到其高度,實質上,該語句計算Rectangle
的默認高度。請注意,在執行此語句以後,程序再也不具備對建立的Rectangle
的引用,由於程序從未在任何地方存儲引用,該對象未被引用,其資源可由Java虛擬機自由回收。
你還可使用對象引用來調用對象的方法,將方法的簡單名稱附加到對象引用,並使用插入點運算符(.
),此外,你在括號內提供方法的任何參數,若是方法不須要任何參數,請使用空括號。
objectReference.methodName(argumentList);
或者:
objectReference.methodName();
Rectangle
類有兩個方法:getArea()
用於計算矩形面積,move()
用於更改矩形的原點,這是調用這兩個方法的CreateObjectDemo
代碼:
System.out.println("Area of rectOne: " + rectOne.getArea()); ... rectTwo.move(40, 72);
第一個語句調用rectOne
的getArea()
方法並顯示結果,第二行移動rectTwo
,由於move()
方法爲對象的origin.x
和origin.y
分配新值。
與實例字段同樣,objectReference
必須是對象的引用,你可使用變量名稱,但也可使用任何返回對象引用的表達式,new
運算符返回一個對象引用,所以你可使用new
返回的值來調用新對象的方法:
new Rectangle(100, 50).getArea()
表達式new Rectangle(100, 50)
返回引用Rectangle
對象的對象引用,如圖所示,你可使用點表示法來調用新的Rectangle
的getArea()
方法來計算新矩形的面積。
某些方法,如getArea()
返回一個值,對於返回值的方法,能夠在表達式中使用方法調用,你能夠將返回值分配給變量,使用它來作出決策或控制循環,此代碼將getArea()
返回的值賦給變量areaOfRectangle
:
int areaOfRectangle = new Rectangle(100, 50).getArea();
請記住,在特定對象上調用方法與向該對象發送消息相同,在這種狀況下,調用getArea()
的對象是構造函數返回的矩形。
某些面向對象的語言要求你跟蹤所建立的全部對象,並在再也不須要時明確銷燬它們,明確地管理內存是乏味且容易出錯的,Java平臺容許你根據須要建立任意數量的對象(固然,受系統能夠處理的限制),你沒必要關心銷燬它們。Java運行時環境在肯定再也不使用對象時刪除對象,此過程稱爲垃圾回收。
當沒有對該對象的引用時,對象有資格進行垃圾回收,當變量超出範圍時,一般會刪除變量中保存的引用,或者,你能夠經過將變量設置爲特殊值null
來顯式刪除對象引用。請記住,程序能夠對同一對象具備多個引用;在對象符合垃圾回收條件以前,必須刪除對對象的全部引用。
Java運行時環境具備垃圾收集器,能夠按期釋放再也不引用的對象使用的內存,垃圾收集器在肯定時間正確時自動完成其工做。