類的更多方面
本節(jié)介紹依賴于使用對象引用的類的更多方面以及你在前面的對象部分中了解到的點運算符。
從方法返回值方法返回到調用它的代碼。
完成方法中的所有語句。
到達return語句。
或拋出異常(稍后介紹)。
以先發(fā)生者為準。
你在方法聲明中聲明方法的返回類型,在方法體內,使用return語句返回值。
聲明為void的任何方法都不返回值,它不需要包含return語句,但它可能會這樣做,在這種情況下,可以使用return語句分支出控制流程塊并退出該方法,并且可以像這樣使用:
return;
如果你嘗試從聲明為void的方法返回值,則會出現(xiàn)編譯器錯誤。
任何未聲明為void的方法都必須包含帶有相應返回值的return語句,如下所示:
return returnValue;
返回值的數(shù)據(jù)類型必須與方法聲明的返回類型匹配,你不能從聲明為返回布爾值的方法返回一個整數(shù)值。
在對象部分中討論的Rectangle類中的getArea()方法返回一個整數(shù):
// a method for computing the area of the rectangle public int getArea() { return width * height; }
此方法返回表達式width * height求值的整數(shù)。
getArea方法返回基本類型,方法還可以返回引用類型,例如,在一個操作Bicycle對象的程序中,我們可能有這樣的方法:
public Bicycle seeWhosFastest(Bicycle myBike, Bicycle yourBike, Environment env) { Bicycle fastest; // code to calculate which bike is // faster, given each bike"s gear // and cadence and given the // environment (terrain and wind) return fastest; }返回類或接口
如果此部分讓你感到困惑,請?zhí)^它并在完成接口和繼承課程后返回該部分。
當一個方法使用類名作為其返回類型時,例如whosFastest,返回對象的類型類必須是返回類型的子類或確切的類。假設你有一個類層次結構,其中ImaginaryNumber是java.lang.Number的子類,而java.lang.Number又是Object的子類,如下圖所示。
現(xiàn)在假設你有一個聲明為返回Number的方法:
public Number returnANumber() { ... }
returnANumber方法可以返回ImaginaryNumber而不是Object,ImaginaryNumber是一個Number,因為它是Number的子類,但是,Object不一定是Number — 它可以是String或其他類型。
你可以重寫方法并定義它以返回原始子類的方法,如下所示:
public ImaginaryNumber returnANumber() { ... }
這種稱為協(xié)變返回類型的技術意味著允許返回類型在與子類相同的方向上變化。
注意:你還可以使用接口名稱作為返回類型,在這種情況下,返回的對象必須實現(xiàn)指定的接口。使用this關鍵字
在實例方法或構造函數(shù)中,這是對當前對象的引用 — 正在調用其方法或構造函數(shù)的對象,你可以使用此方法從實例方法或構造函數(shù)中引用當前對象的任何成員。
將this與字段一起使用使用this關鍵字的最常見原因是因為字段被方法或構造函數(shù)參數(shù)遮蔽。
例如,Point類就是這樣寫的:
public class Point { public int x = 0; public int y = 0; //constructor public Point(int a, int b) { x = a; y = b; } }
但它可能是這樣寫的:
public class Point { public int x = 0; public int y = 0; //constructor public Point(int x, int y) { this.x = x; this.y = y; } }
構造函數(shù)的每個參數(shù)都會影響對象的一個??字段 — 構造函數(shù)內部的x是構造函數(shù)的第一個參數(shù)的本地副本,要引用Point字段x,構造函數(shù)必須使用this.x。
將this與構造函數(shù)一起使用在構造函數(shù)中,你還可以使用this關鍵字來調用同一個類中的另一個構造函數(shù),這樣做稱為顯式構造函數(shù)調用,這是另一個Rectangle類,其實現(xiàn)與對象部分中的實現(xiàn)不同。
public class Rectangle { private int x, y; private int width, height; public Rectangle() { this(0, 0, 1, 1); } public Rectangle(int width, int height) { this(0, 0, width, height); } public Rectangle(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; } ... }
該類包含一組構造函數(shù),每個構造函數(shù)初始化一些或所有矩形的成員變量,構造函數(shù)為任何成員變量提供默認值,其初始值不是由參數(shù)提供的。例如,無參數(shù)構造函數(shù)在坐標0,0處創(chuàng)建1x1矩形。雙參數(shù)構造函數(shù)調用四參數(shù)構造函數(shù),傳遞寬度和高度,但始終使用0,0坐標,和之前一樣,編譯器根據(jù)參數(shù)的數(shù)量和類型確定要調用的構造函數(shù)。
如果存在,則另一個構造函數(shù)的調用必須是構造函數(shù)中的第一行。
控制對類成員的訪問訪問級別修飾符確定其他類是否可以使用特定字段或調用特定方法,訪問控制有兩個級別:
在頂級 — public或package-private(沒有顯式修飾符)。
在成員級別 — public、private、protected或package-private(無顯式修飾符)。
可以使用修飾符public聲明一個類,在這種情況下,該類對于所有類都可見,如果一個類沒有修飾符(默認,也稱為包私有),它只在自己的包中可見(包是相關類的命名組 — 你將在后面的課程中了解它們)。
在成員級別,你也可以使用public修飾符或無修飾符(package-private),就像使用頂級類一樣,并且具有相同的含義。對于成員,還有兩個額外的訪問修飾符:private和protected,private修飾符指定只能在其自己的類中訪問該成員,protected修飾符指定只能在其自己的包中訪問該成員(與package-private一樣),此外,還可以在另一個包中通過其類的子類訪問該成員。
下表顯示了每個修飾符允許的成員訪問權限。
修飾符 | 類 | 包 | 子類 | 所有 |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
無修飾符 | Y | Y | N | N |
private | Y | N | N | N |
第一個數(shù)據(jù)列指示類本身是否可以訪問由訪問級別定義的成員,如你所見,類始終可以訪問自己的成員,第二列指示與該類相同的包中的類(不管父子關系)可以訪問該成員,第三列指示在此包外聲明的該類的子類是否可以訪問該成員,第四列指示是否所有類都可以訪問該成員。
訪問級別以兩種方式影響你,首先,當你使用來自其他源的類(例如Java平臺中的類)時,訪問級別將確定你自己的類可以使用的那些類的哪些成員,其次,當你編寫一個類時,你需要確定每個成員變量和類中的每個方法應具有的訪問級別。
讓我們看一下類的集合,看看訪問級別如何影響可見性,下圖顯示了此示例中的四個類以及它們之間的關系。
下表顯示了Alpha類的成員對于可應用于它們的每個訪問修飾符的可見性。
修飾符 | Alpha | Beta | Alphasub | Gamma |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
無修飾符 | Y | Y | N | N |
private | Y | N | N | N |
選擇訪問級別的提示:
如果其他程序員使用你的類,你希望確保不會發(fā)生濫用錯誤,訪問級別可以幫助你執(zhí)行此操作。
使用對特定成員有意義的最嚴格的訪問級別,除非你有充分的理由不使用private。
避免除常量之外的public字段(本教程中的許多示例都使用public字段,這可能有助于簡明地說明一些要點,但不建議用于生產(chǎn)代碼),public字段傾向于將你鏈接到特定實現(xiàn),并限制你更改代碼的靈活性。
了解類成員在本節(jié)中,我們將討論使用static關鍵字創(chuàng)建屬于類的字段和方法,而不是類的實例。
類變量當從同一個類藍圖創(chuàng)建許多對象時,它們每個都有自己不同的實例變量副本,在Bicycle類的情況下,實例變量是cadence、gear和speed,每個Bicycle對象都有這些變量自己的值,這些變量存儲在不同的內存位置。
有時,你希望擁有所有對象共有的變量,這是通過static修飾符完成的,在聲明中具有static修飾符的字段稱為靜態(tài)字段或類變量,它們與類相關聯(lián),而不是與任何對象相關聯(lián),該類的每個實例共享一個類變量,該變量位于內存中的一個固定位置,任何對象都可以更改類變量的值,但也可以在不創(chuàng)建類實例的情況下操作類變量。
例如,假設你要創(chuàng)建多個Bicycle對象并為每個對象分配一個序列號,從第一個對象開始為1,此ID號對于每個對象都是唯一的,因此是一個實例變量。同時,你需要一個字段來跟蹤已創(chuàng)建的Bicycle對象的數(shù)量,以便你知道要分配給下一個對象的ID,這樣的字段與任何單個對象無關,而與整個類有關,為此,你需要一個類變量numberOfBicycles,如下所示:
public class Bicycle { private int cadence; private int gear; private int speed; // add an instance variable for the object ID private int id; // add a class variable for the // number of Bicycle objects instantiated private static int numberOfBicycles = 0; ... }
類變量由類名本身引用,如:
Bicycle.numberOfBicycles
這清楚地表明它們是類變量。
注意:你也可以使用對象引用來引用靜態(tài)字段myBike.numberOfBicycles,但這是不鼓勵的,因為它沒有說明它們是類變量。
你可以使用Bicycle構造函數(shù)來設置id實例變量并增加numberOfBicycles類變量:
public class Bicycle { private int cadence; private int gear; private int speed; private int id; private static int numberOfBicycles = 0; public Bicycle(int startCadence, int startSpeed, int startGear){ gear = startGear; cadence = startCadence; speed = startSpeed; // increment number of Bicycles // and assign ID number id = ++numberOfBicycles; } // new method to return the ID instance variable public int getID() { return id; } ... }類方法
Java編程語言支持靜態(tài)方法以及靜態(tài)變量,靜態(tài)方法在其聲明中具有static修飾符,應該使用類名調用,而不需要創(chuàng)建類的實例,如:
ClassName.methodName(args)
注意:你也可以使用對象引用來引用靜態(tài)方法instanceName.methodName(args),但這是不鼓勵的,因為它沒有說明它們是類方法。
靜態(tài)方法的常見用途是訪問靜態(tài)字段,例如,我們可以向Bicycle類添加一個靜態(tài)方法來訪問numberOfBicycles靜態(tài)字段:
public static int getNumberOfBicycles() { return numberOfBicycles; }
并非所有實例和類變量和方法的組合都是允許的:
實例方法可以直接訪問實例變量和實例方法。
實例方法可以直接訪問類變量和類方法。
類方法可以直接訪問類變量和類方法。
類方法不能直接訪問實例變量或實例方法 — 它們必須使用對象引用,此外,類方法不能使用this關鍵字,因為沒有要引用的實例。
常量static修飾符與final修飾符結合使用,也用于定義常量,final修飾符表示此字段的值不能更改。
例如,以下變量聲明定義了一個名為PI的常量,其值是pi的近似值(圓周長與直徑之比):
static final double PI = 3.141592653589793;
以這種方式定義的常量不能重新分配,如果你的程序嘗試這樣做,則它是編譯時錯誤,按照慣例,常量值的名稱拼寫為大寫字母,如果名稱由多個單詞組成,則單詞由下劃線(_)分隔。
注意:如果將基本類型或字符串定義為常量并且該值在編譯時已知,則編譯器會將代碼中的常量名稱替換為其值,這稱為編譯時常量。如果外部世界中常量的值發(fā)生變化(例如,如果立法規(guī)定pi實際上應該是3.975),則需要重新編譯使用此常量來獲取當前值的任何類。Bicycle類
在本節(jié)中進行了所有修改之后,Bicycle類現(xiàn)在是:
public class Bicycle { private int cadence; private int gear; private int speed; private int id; private static int numberOfBicycles = 0; public Bicycle(int startCadence, int startSpeed, int startGear) { gear = startGear; cadence = startCadence; speed = startSpeed; id = ++numberOfBicycles; } public int getID() { return id; } public static int getNumberOfBicycles() { return numberOfBicycles; } public int getCadence() { return cadence; } public void setCadence(int newValue) { cadence = newValue; } public int getGear(){ return gear; } public void setGear(int newValue) { gear = newValue; } public int getSpeed() { return speed; } public void applyBrake(int decrement) { speed -= decrement; } public void speedUp(int increment) { speed += increment; } }初始化字段
如你所見,你通??梢栽谄渎暶髦袨樽侄翁峁┏跏贾担?/p>
public class BedAndBreakfast { // initialize to 10 public static int capacity = 10; // initialize to false private boolean full = false; }
當初始化值可用并且初始化可以放在一行上時,這很有效,然而,這種形式的初始化由于其簡單性而具有局限性,如果初始化需要一些邏輯(例如,錯誤處理或for循環(huán)來填充復雜數(shù)組),則簡單的賦值是不合適的。實例變量可以在構造函數(shù)中初始化,其中可以使用錯誤處理或其他邏輯,為了為類變量提供相同的功能,Java編程語言包括靜態(tài)初始化塊。
注意:沒有必要在類定義的開頭聲明字段,盡管這是最常見的做法,只有在使用它們之前才需要聲明和初始化它們。靜態(tài)初始化塊
靜態(tài)初始化塊是用大括號{}括起來的常規(guī)代碼塊,前面是static關鍵字,這是一個例子:
static { // whatever code is needed for initialization goes here }
一個類可以有任意數(shù)量的靜態(tài)初始化塊,它們可以出現(xiàn)在類體中的任何位置,運行時系統(tǒng)保證按照它們在源代碼中出現(xiàn)的順序調用靜態(tài)初始化塊。
還有靜態(tài)塊的替代方法 — 你可以編寫私有靜態(tài)方法:
class Whatever { public static varType myVar = initializeClassVariable(); private static varType initializeClassVariable() { // initialization code goes here } }
私有靜態(tài)方法的優(yōu)點是,如果需要重新初始化類變量,可以在以后重用它們。
初始化實例成員通常,你可以使用代碼在構造函數(shù)中初始化實例變量,使用構造函數(shù)初始化實例變量有兩種選擇:初始化塊和final方法。
實例變量的初始化程序塊看起來就像靜態(tài)初始化程序塊,但沒有static關鍵字:
{ // whatever code is needed for initialization goes here }
Java編譯器將初始化程序塊復制到每個構造函數(shù)中,因此,該方法可用于在多個構造函數(shù)之間共享代碼塊。
無法在子類中重寫final方法,這在接口和繼承的課程中討論,以下是使用final方法初始化實例變量的示例:
class Whatever { private varType myVar = initializeInstanceVariable(); protected final varType initializeInstanceVariable() { // initialization code goes here } }
如果子類可能想要重用初始化方法,這尤其有用,該方法是final,因為在實例初始化期間調用非final方法可能會導致問題。
創(chuàng)建和使用類和對象的總結類聲明為類命名,并將類主體括在大括號之間,類名可以在前面加上修飾符,類主體包含類的字段、方法和構造函數(shù),類使用字段來包含狀態(tài)信息,并使用方法來實現(xiàn)行為,初始化類的新實例的構造函數(shù)使用類的名稱,看起來像沒有返回類型的方法。
你可以通過相同的方式控制對類和成員的訪問:在聲明中使用諸如public之類的訪問修飾符。
你可以通過在成員聲明中使用static關鍵字來指定類變量或類方法,未聲明為static的成員隱式地是實例成員,類變量由類的所有實例共享,可以通過類名和實例引用來訪問,類的實例獲取每個實例變量的自己的副本,必須通過實例引用訪問它們。
你可以使用new運算符和構造函數(shù)從類創(chuàng)建對象,new運算符返回對已創(chuàng)建對象的引用,你可以將引用分配給變量或直接使用它。
可以通過使用限定名稱來引用可在其聲明的類之外的代碼訪問的實例變量和方法,實例變量的限定名稱如下所示:
objectReference.variableName
方法的限定名稱如下所示:
objectReference.methodName(argumentList)
或者:
objectReference.methodName()
垃圾收集器自動清理未使用的對象,如果程序不再包含對它的引用,則不使用該對象,你可以通過將包含引用的變量設置為null來顯式刪除引用。
上一篇: 對象 下一篇:嵌套類文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://www.ezyhdfw.cn/yun/72302.html
Java? 教程 Java教程是為JDK 8編寫的,本頁面中描述的示例和實踐沒有利用在后續(xù)版本中引入的改進。 Java教程是希望使用Java編程語言創(chuàng)建應用程序的程序員的實用指南,其中包括數(shù)百個完整的工作示例和數(shù)十個課程,相關課程組被組織成教程。 覆蓋基礎知識的路徑 這些教程以書籍的形式提供,如Java教程,第六版,前往Amazon.com購買。 入門 介紹Java技術和安裝Java開發(fā)軟件并使用...
對象 典型的Java程序會創(chuàng)建許多對象,如你所知,通過調用方法進行交互,通過這些對象交互,程序可以執(zhí)行各種任務,例如實現(xiàn)GUI,運行動畫或通過網(wǎng)絡發(fā)送和接收信息,一旦對象完成了創(chuàng)建它的工作,它的資源就會被回收以供其他對象使用。 這是一個名為CreateObjectDemo的小程序,它創(chuàng)建了三個對象:一個Point對象和兩個Rectangle對象,你將需要所有三個源文件來編譯此程序。 public ...
摘要:反對者在某些領域對此予以否認。下面再引用一段來自維基百科中關于的歷史。類的更嚴格的定義是由某種特定的元數(shù)據(jù)所組成的內聚的包。類還可以有運行時表示形式元對象,它為操作與類相關的元數(shù)據(jù)提供了運行時支持。 在開始部分,請看官非常非常耐心地閱讀下面幾個枯燥的術語解釋,本來這不符合本教程的風格,但是,請看官諒解,因為列位將來一定要閱讀枯燥的東西的。這些枯燥的屬于解釋,均來自維基百科。 1、問題...
摘要:它們是通過來自遠程的服務器的連接發(fā)送字節(jié)碼并在本地運行,這一點令人興奮。中有一個自定義的,它不是從本地文件系統(tǒng)加載類文件,而是從遠程服務器上獲取,通過加載原始字節(jié)碼,再在中轉化為類。它將字節(jié)碼解析為運行時的數(shù)據(jù)結構,檢查其有效性等。 前言 Java ClassLoader是java運行系統(tǒng)中一個至關重要但是經(jīng)常被忽略的組件。它負責在運行時尋找并加載類文件。創(chuàng)建自定義的ClassLoad...
多態(tài)性 多態(tài)性的字典定義是指生物學中的原理,其中生物體或物種可以具有許多不同的形式或階段,這個原則也可以應用于面向對象的編程和像Java語言之類的語言,類的子類可以定義它們自己的唯一行為,但仍然共享父類的一些相同功能。 可以通過對Bicycle類的微小修改來演示多態(tài)性,例如,可以將printDescription方法添加到顯示當前存儲在實例中的所有數(shù)據(jù)的類中。 public void printD...
閱讀 1026·2021-11-24 10:42
閱讀 3576·2021-11-19 11:34
閱讀 2715·2021-09-29 09:35
閱讀 2607·2021-09-09 09:33
閱讀 750·2021-07-26 23:38
閱讀 2588·2019-08-30 10:48
閱讀 1451·2019-08-28 18:07
閱讀 480·2019-08-26 13:44