Java™ 教程(對象)

對象

典型的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

  1. 聲明:等號前面的代碼是將變量名稱與對象類型相關聯的全部變量聲明。
  2. 實例化:new關鍵字是一個建立對象的Java運算符。
  3. 初始化:new運算符後面是對構造函數的調用,該構造函數初始化新對象。

聲明變量以引用對象

以前,你瞭解到要聲明變量,你能夠編寫:code

type name;

這會通知編譯器你將使用name來引用類型爲type的數據,對於原始變量,此聲明還爲變量保留適當的內存量。對象

你還能夠在本身的代碼行上聲明引用變量,例如:blog

Point originOne;

若是你像這樣聲明originOne,它的值將不肯定,直到實際建立並分配了一個對象,簡單地聲明引用變量不會建立對象,爲此,你須要使用new運算符,以下一節所述,在代碼中使用對象以前,必須將對象分配給originOne,不然,你將收到編譯器錯誤。

此狀態中的變量(當前不引用任何對象)能夠以下所示(變量名稱,originOne,以及指向無的引用):

objects-null.gif

實例化一個類

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)聲明,如下語句提供2394做爲這些參數的值:

Point originOne = new Point(23, 94);

執行此語句的結果能夠在下圖中說明:

objects-oneRef.gif

這是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;
    }
}

每一個構造函數都容許你使用基本類型和引用類型爲矩形的originwidthheight提供初始值,若是一個類有多個構造函數,則它們必須具備不一樣的簽名,Java編譯器根據參數的數量和類型區分構造函數。當Java編譯器遇到如下代碼時,它知道在Rectangle類中調用構造函數,該構造函數須要一個Point參數後跟兩個整數參數:

Rectangle rectOne = new Rectangle(originOne, 100, 200);

這就要求Rectangle的一個構造初始化原點originOne,此外,構造函數將width設置爲100,將height設置爲200,如今有兩個對同一個Point對象的引用 — 一個對象能夠有多個對它的引用,以下圖所示:

objects-multipleRefs.gif

如下代碼行調用Rectangle構造函數,該構造函數須要兩個整數參數,這些參數提供widthheight的初始值,若是檢查構造函數中的代碼,你將看到它建立了一個新的Point對象,其xy值初始化爲0

Rectangle rectTwo = new Rectangle(50, 100);

如下語句中使用的Rectangle構造函數不帶任何參數,所以它被稱爲無參數構造函數:

Rectangle rect = new Rectangle();

全部類至少有一個構造函數,若是類沒有顯式聲明任何,則Java編譯器會自動提供一個無參數構造函數,稱爲默認構造函數。此默認構造函數調用父類的無參數構造函數,若是類沒有其餘父級,則調用Object構造函數,若是父級沒有構造函數(Object確實有構造函數),編譯器將拒絕該程序。

使用對象

一旦你建立了一個對象,你可能想要用它來作某事,你可能須要使用其中一個字段的值,更改其中一個字段,或調用其中一個方法來執行操做。

引用對象的字段

對象字段按名稱訪問,你必須使用明確的名稱。

你能夠在其本身的類中對於字段使用簡單名稱,例如,咱們能夠在Rectangle類中添加一個打印widthheight的語句:

System.out.println("Width and height are: " + width + ", " + height);

在這種狀況下,widthheight是簡單的名稱。

對象類外部的代碼必須使用對象引用或表達式,後跟點(.)運算符,後跟簡單字段名稱,以下所示:

objectReference.fieldName

例如,CreateObjectDemo類中的代碼位於Rectangle類的代碼以外,所以,要引用名爲rectOneRectangle對象中的originwidthheight字段,CreateObjectDemo類必須分別使用名稱rectOne.originrectOne.widthrectOne.height,該程序使用其中兩個名稱來顯示rectOnewidthheight

System.out.println("Width of rectOne: "  + rectOne.width);
System.out.println("Height of rectOne: " + rectOne.height);

嘗試在CreateObjectDemo類中的代碼使用簡單名稱的widthheight沒有意義 — 這些字段僅存在於對象中 — 並致使編譯器錯誤。

稍後,該程序使用相似的代碼來顯示有關rectTwo的信息,相同類型的對象具備本身的相同實例字段的副本,所以,每一個Rectangle對象都有名爲originwidthheight的字段。經過對象引用訪問實例字段時,將引用該特定對象的字段,CreateObjectDemo程序中的兩個對象rectOnerectTwo具備不一樣的originwidthheight字段。

要訪問字段,你可使用對象的命名引用,如前面的示例所示,或者你可使用任何返回對象引用的表達式。回想一下,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);

第一個語句調用rectOnegetArea()方法並顯示結果,第二行移動rectTwo,由於move()方法爲對象的origin.xorigin.y分配新值。

與實例字段同樣,objectReference必須是對象的引用,你可使用變量名稱,但也可使用任何返回對象引用的表達式,new運算符返回一個對象引用,所以你可使用new返回的值來調用新對象的方法:

new Rectangle(100, 50).getArea()

表達式new Rectangle(100, 50)返回引用Rectangle對象的對象引用,如圖所示,你可使用點表示法來調用新的RectanglegetArea()方法來計算新矩形的面積。

某些方法,如getArea()返回一個值,對於返回值的方法,能夠在表達式中使用方法調用,你能夠將返回值分配給變量,使用它來作出決策或控制循環,此代碼將getArea()返回的值賦給變量areaOfRectangle

int areaOfRectangle = new Rectangle(100, 50).getArea();

請記住,在特定對象上調用方法與向該對象發送消息相同,在這種狀況下,調用getArea()的對象是構造函數返回的矩形。

垃圾收集器

某些面向對象的語言要求你跟蹤所建立的全部對象,並在再也不須要時明確銷燬它們,明確地管理內存是乏味且容易出錯的,Java平臺容許你根據須要建立任意數量的對象(固然,受系統能夠處理的限制),你沒必要關心銷燬它們。Java運行時環境在肯定再也不使用對象時刪除對象,此過程稱爲垃圾回收。

當沒有對該對象的引用時,對象有資格進行垃圾回收,當變量超出範圍時,一般會刪除變量中保存的引用,或者,你能夠經過將變量設置爲特殊值null來顯式刪除對象引用。請記住,程序能夠對同一對象具備多個引用;在對象符合垃圾回收條件以前,必須刪除對對象的全部引用。

Java運行時環境具備垃圾收集器,能夠按期釋放再也不引用的對象使用的內存,垃圾收集器在肯定時間正確時自動完成其工做。


上一篇:類

下一篇:類的更多方面

相關文章
相關標籤/搜索