天天看點

《Java語言導學(原書第6版)》一3.1 變量

根據第2章可知,對象的狀态存儲在字段中:

《Java語言導學(原書第6版)》一3.1 變量

2.1節已經介紹了字段的概念,但讀者仍可能會問:命名字段有什麼規則和約定 除了整型,是否還有其他資料類型?字段在聲明時是否必須初始化?如果字段沒有顯式初始化,該字段是否會被賦予一個預設值?本章将會詳細解答這些問題。但在此之前,先要明确一些技術差别。Java程式語言同時使用字段和變量。對于新的開發人員而言,這是造成概念混淆的主要原因,因為兩者經常看似指代同一個事物。Java程式語言定義了如下變量:

執行個體變量(非靜态字段)。就技術而言,對象将個體狀态存入非靜态字段,也就是不用關鍵字static聲明的字段。非靜态字段也稱為執行個體變量,因為對每個類執行個體(即對象)而言,它們的值都是唯一的。比如,一輛自行車的currentSpeed字段與另一輛自行車的currentSpeed字段無關。

類變量(靜态字段)。類變量是用static修飾符聲明的任意字段,這就告訴編譯器該變量隻存在一個副本,而不管它被執行個體化多少次。特定類型的自行車的檔數字段定義時要用static來聲明,因為該檔數會應用于所有的執行個體。代碼static int numGears=6;建立該靜态字段。此外,也可以添加關鍵字final表示該檔數永遠都不會變。

局部變量。與對象将狀态存入字段類似,方法也将臨時狀态存入局部變量。聲明局部變量的文法與聲明字段類似(例如int count=0;)。局部變量在聲明時沒有特殊的關鍵字,完全取決于變量的聲明位置,也就是說方法體内有效。是以,局部變量隻對聲明它的方法可見,類的其他部分不能通路該局部變量。

參數。在Bicycle類和“Hello World!”執行個體程式的main方法中我們已經見到過參數的例子。main方法的聲明形式是public static void main(String[] args)。其中,變量args是main方法的參數。最重要的一點是,參數總被歸為變量,而不是字段。這同樣适用于後續章節将要學習的其他支援參數的構造,如構造器和異常處理器。

即便如此,本章後續内容讨論字段和變量時仍采用下述标準進行區分。如果讨論的是一般的字段(不包括局部變量和參數),就采用術語字段。如果讨論适用于上述四種變量,就采用術語變量。如果上下文要求進行區分,就根據情況采用特定的術語(靜态字段、局部變量等)。有時也會使用術語成員(member)。類型的字段、方法和嵌入類型等都是它的成員。

程式語言都有自己的命名規則和約定,Java也不例外,其變量的命名有以下規則和約定:

變量名區分大小寫。變量名可以是任意合法的辨別符,如以字母、美元符号($)或下劃線(_)開頭的無限長的Unicode字母和數字序列。但是,按約定通常采用字母開頭,而不是美元符号或下劃線。另外,按約定美元符号從來沒有使用過。盡管有些自動生成的變量名會包含美元符号,但命名變量時應該盡量避免。這些同樣适用于下劃線。雖然以下劃線開頭命名變量是合法的,但并不鼓勵采用該方法。變量命名時不支援空格。

确定首個字元之後,後續字元可以是字母、數字、美元符号或下劃線。當然也有一些約定或常識。命名變量時最好使用完整的單詞,而不是神秘的縮寫。這樣命名可以提高代碼的可讀性。大多數情況下,這樣做會提高代碼的自文檔化(self-documenting)程度。比如,字段名cadence、speed、gear比縮寫c、s、g更直覺。切記,變量名不能是關鍵字或保留字。

如果變量名隻包含一個單詞,就用小寫字母表示。如果包含兩個或兩個以上單詞,後續單詞的首字母要大寫,如gearRatio和currentGear。如果變量儲存的是常量值,如static final int NUM_GEARS=6,那麼變量名的每個字母都要大寫,而且後續單詞用下劃線分隔。按約定,其他情況都不用下劃線。

Java是靜态類型的程式語言,也就是說,所有變量在使用前必須先聲明。聲明的内容包括類型和名稱,如:

《Java語言導學(原書第6版)》一3.1 變量

該聲明告訴程式存在一個字段gear,其資料為數字類型,初始值為1。變量的資料類型決定它可以包含的值以及該變量上可以執行的運算。除了整型(int)以外,Java程式語言還支援其他7種基本資料類型。基本資料類型由語言預定義并用保留關鍵字命名。基本資料類型的值之間不共享狀态。Java程式語言支援以下8種基本資料類型。

1)byte資料類型表示8位帶符号二進制補碼整數。其最小值為-128,最大值為127。當大型數組的記憶體存儲出問題時,byte資料類型可用于存儲記憶體。byte類型變量的範圍有限,可以作為一種文檔規範。是以,它也用于代替int類型以簡化代碼。

2)short資料類型表示16位帶符号二進制補碼整數。其最小值為-32?768,最大值為32?767。與byte類型一樣,short類型也可以用作大型數組記憶體存儲的應急方案。

3)int資料類型表示32位帶符号二進制補碼整數。其最小值為-231,最大值為231-1。在Java SE 8及更高版本中,可以使用int資料類型表示無符号32位整數,其最小值為0,最大值為232-1。Interger類也支援無符号32位整數。Interger類中增加了類似于compareUnsigned和divideUnsigned的靜态方法以支援無符号整數的算術運算。

4)long資料類型表示64位帶符号二進制補碼整數。其最小值為-263,最大值為263-1。在Java SE 8及更高版本中,可以使用long資料類型表示無符号64位長整型整數,其最小值為0,最大值為264-1。使用的值超出int資料類型支援的範圍時可使用該資料類型。Long類也包含類似于compareUnsigned和devideUnsigned的方法以支援無符号長整型數的算術運算。

5)float資料類型表示單精度32位IEEE 754浮點數。其值的分布範圍超出本書的讨論範疇,可參考Java語言規範(Java Language Specification)中的“浮點類型、格式和值”部分。與byte和short類型一樣,如果要在浮點型大型數組中存儲記憶體,可以采用該類型(而不用下面的double類型)。該類型不能用于表示精确的值,如貨币。要表示精确的值,可以使用java.math.BigDecimal類。第9章将會介紹BigDecimal和其他有用的類。

6)double資料類型表示雙精度64位IEEE 754浮點數。其值的分布範圍超出本書的讨論範疇,可參考Java語言規範中的“浮點類型、格式和值”部分。通常,該資料類型是小數的預設類型。如前所述,也不能用于表示貨币等精确值。

7)boolean資料類型隻有兩個可能值:true和false。它主要用于标記true或false條件。該資料類型表示1位資訊,但其“大小”并未精确定義。

8)char資料類型表示16位Unicode字元。其最小值為'u0000'(或0),最大值為'uffff'(或65 535)。

除了這8種基本資料類型外,Java程式語言還提供java.lang.String類支援字元串。将字元串加上雙引号會自動建立一個新的String對象,如String s="this is a string";。String對象是不可變的。也就是說,String對象一旦建立,其值就不能改變。就技術而言,String類不是基本資料類型。但考慮到Java對其提供特殊支援,你可能會認為它也是一種基本資料類型。String類的詳情參見第9章。

1.預設值

字段聲明時,不一定總要賦初值。編譯器會為那些已經聲明但未初始化的字段賦予一個預設值。預設值通常為0或null,這取決于資料類型。但是依賴預設值的做法是一種不好的程式設計習慣。表3-1總結了上述資料類型的預設值。

《Java語言導學(原書第6版)》一3.1 變量

局部變量的處理方式略有不同,編譯器不會為未初始化的局部變量賦初值。如果局部變量在聲明時不能初始化,那麼使用該局部變量之前必須為其指派。通路未初始化的局部變量會導緻編譯時錯誤。

2.字

大家可能已經注意到,初始化基本類型的變量時不能使用關鍵字new。基本類型是内嵌在Java語言中的特殊資料類型,它們不需要用類來建立。字(或文字,literal)是用源代碼表示的固定值。字不需要計算,直接由代碼表示。下面給出為主類型變量指派字的例子:

《Java語言導學(原書第6版)》一3.1 變量

(1)整型字

整型字如果以L或l結尾,就是long類型的;否則就是int類型的。建議使用大寫字母L,因為小寫字母l與數字1很難區分。

byte、short、int和long類型的整數值可以由int類型的字建立。超出int值範圍的long類型的值,可以由long類型的字建立。整型字可以由下述記數系統表示:

十進制。基數為10,數字由0到9的整數組成。這也是我們日常用的記數系統。

十六進制。基數為16,數字由0到9的整數和A到F的大寫字母組成。

二進制。基數為2,組成數字隻有0和1。

通常的程式設計中,十進制系統可能是人們唯一用過的記數系統。如果要用其他數制系統,要注意其文法的正确性,字首0x表示十六進制數,字首0b表示二進制數,例子如下。

(2)浮點字

浮點字是以字母F或f結尾的float類型的字,或是以字母D或d結尾的double類型的字。浮點字的表示方法有三種:用E或e表示科學記數标記,用F或f表示32位float類型的字,用D或d表示64位double類型的字(預設類型,通常省略)。

《Java語言導學(原書第6版)》一3.1 變量

(3)字元字和字元串字

char和String類型的字可以包含任意Unicode(UTF-16)字元。如果編輯器和檔案系統支援,可以直接在編碼中使用這些字元。如果不支援,可以使用轉義字元,如用'u0108'表示?,用"Su00ED Seu00Flor"表示西班牙文Sí Senor。用單引号表示字元字,用雙引号表示字元串字。轉義序列也可以用在程式中的其他地方(如字段名),而不僅僅是字元字或字元串字。

Java程式語言也支援一些特殊的char和String類型的轉義序列:b(倒退)、t(跳格)、n(換行)、f(換頁)、r(回車)、"(雙引号)、'(單引号)和\(反斜杠)。

null是一個特殊的字,它可以用作任意引用類型的值。null可以指派給任意主類型外的其他變量。除了用于測試存在性外,null值很少有其他用處。是以,它通常用于标記某個對象是否可用。

最後還有一種特殊的類字(class literal),其表示形式為“類名.class”(如String.class)。這類字指表示類型本身的對象。

3.在數字文字中使用下劃線

數字文字中的數字之間可以使用任意多個下劃線(_)。這樣就可以對數字文字進行分組,進而提高代碼的可讀性。

例如,如果代碼中包含很多數字組成的數,就可以用下劃線将這些數字分成3個一組,其用法與逗号和空格一樣。

下面的例子給出了在數字文字中使用下劃線的其他方式:

《Java語言導學(原書第6版)》一3.1 變量

下劃線隻能放在數字之間,不能放在下述位置:

數的開頭或末尾

浮點字中與小數點相鄰的位置

字尾F或L前面

要求是數字字元串的位置

下面例子說明數字文字中合法和不合法的下劃線放置位置(如黑體所示)。

《Java語言導學(原書第6版)》一3.1 變量
《Java語言導學(原書第6版)》一3.1 變量

數組是固定數目的單一資料類型值的容器對象。建立數組時要指定其長度。建立後,其長度就固定了。“Hello World!”執行個體程式的main方法中已經給出了一個數組執行個體。本小節詳細介紹數組。

《Java語言導學(原書第6版)》一3.1 變量

數組中的每個項都稱作元素(element),每個元素都用數字索引(index)通路。如圖3-1所示,索引從0開始。是以第9個元素要通過索引8來通路。

下面的ArrayDemo程式建立了一個整型數組,存入值并将這些值顯示到标準輸出:

《Java語言導學(原書第6版)》一3.1 變量
《Java語言導學(原書第6版)》一3.1 變量

上述例子清晰地介紹了數組的文法。但真正編寫程式時,可能會用循環構造(looping construct)來疊代數組中的元素,而不是上例中為每個元素都寫一行代碼。循環構造(for、while、do-while)的内容将在3.4節中介紹。

1.聲明變量引用數組

上述程式用下面兩行代碼聲明數組anArray:

《Java語言導學(原書第6版)》一3.1 變量

與其他類型的變量聲明一樣,數組聲明也包含兩個元件:數組類型和數組名。數組的類型寫作type[],其中type是包含的元素的資料類型,方括号表示該變量儲存數組。這種寫法中沒有包含數組大小(這是方括号内為空的原因)。數組名可以是任意名稱,隻要它滿足3.1.1節讨論的命名規則和約定。與其他類型的變量一樣,該聲明不會建立數組,而隻是告訴編譯器該變量可用于儲存特定類型的數組。類似地,可以聲明其他資料類型的數組:

《Java語言導學(原書第6版)》一3.1 變量

也可以将方括号寫在數組名後面:

《Java語言導學(原書第6版)》一3.1 變量

但是,通常不建議采用這種聲明方式。方括号表示數組的類型,應該和類型标記符寫在一起。

2.建立、初始化和通路數組

建立數組的一個方法是使用new運算符。下述語句來自ArrayDemo程式,它配置設定了一個帶有10個整型元素記憶體空間的數組,并将該數組指派給anArray變量:

《Java語言導學(原書第6版)》一3.1 變量

采用這種方式時,數組大小由花括号之間用逗号分隔的值的個數決定。

也可以用兩個或多個方括号聲明多元數組(multidimensional array),如String[][] names。其元素必須用相應的索引值來通路。

Java程式語言中,多元數組是元件也是數組的數組。這一點與C或Fortran語言中的數組不同。是以,每行的長度可以不同,如multiDimArrayDemo程式所示。

《Java語言導學(原書第6版)》一3.1 變量

最後,可以使用内置的length屬性來擷取數組的大小。下述代碼會将數組大小顯示在标準輸出上:

《Java語言導學(原書第6版)》一3.1 變量

3.複制數組

System類有arraycopy方法,可用于數組之間資料的高效複制:

《Java語言導學(原書第6版)》一3.1 變量

兩個Object參數分别指定源數組和目标數組,三個int參數分别指定源數組的起始位置、目标數組的起始位置以及待複制的元素個數。

下述ArrayCopyDemo程式聲明char類型的數組,其元素構成單詞decaffeinated,并使用System (arraycopy)方法将該數組元件的子序列複制到第2個數組中:

《Java語言導學(原書第6版)》一3.1 變量

4.?數組操作

數組是程式設計中重要且有用的概念。Java SE提供了一系列與數組相關的常用操作方法。例如,ArrayCopyDemo例子使用System類的arraycopy()方法,而不是手動将源數組中的元素依次存入目标數組。該過程在背景完成,開發人員隻需使用一行代碼調用該方法即可。

為友善起見,Java SE在java.util.Arrays類中提供了幾個數組操作方法(如複制、排序和查找等常見任務)。例如,可以使用java.util.Arrays類的copyOfRange()方法将前述ArrayCopyDemo方法修改為如下的ArrayCopyOfDemo方法。兩者的差別在于,使用copyOfRange()方法時,調用方法之前不需要建立目标數組,該方法會傳回目标數組。

《Java語言導學(原書第6版)》一3.1 變量

顯然,該例子包含的代碼更少,但程式的輸出仍然一樣,也是caffein。

java.util.Arrays類也提供了其他一些有用的操作方法,例如:

binarySearch()——在數組中搜尋特定值,并傳回其位置索引。

equals()——對兩個數組進行比較,并确定兩者是否相等。

fill()——在數組的每個索引位置上填上指定值。

升序排序方法——Java SE 8引入兩種方法,一種是順序方法sort(),另一種是并發方法parallelSort()。多處理器系統中大數組的并發排序比順序排序要快。

Java程式語言同時采用術語字段和變量。執行個體變量(非靜态字段)對每個類的執行個體都是唯一的。類變量(靜态字段)是用static修飾符聲明的字段。不管類有多少個執行個體,都隻有一個類變量。局部變量表示方法内的臨時狀态。參數是為方法提供附加資訊的變量。局部變量和參數通常歸類為變量,而非字段。命名字段或變量時,應該(或必須)遵守一些命名規則和約定。

八種基本資料類型為byte、short、int、long、float、double、boolean和char。java.lang.String表示字元串。編譯器會為這些類型的字段指派一個預設值,但不會為局部變量指派預設值。字(文字)是固定值的源代碼表示。數組是固定數目的單一資料類型值的容器對象。建立數組時要指定其長度。建立後,數組長度就固定了。

問題

執行個體化變量又叫作     。

類變量又叫作     。

局部變量存儲臨時狀态,它在     内聲明。

方法體内聲明的變量叫     。

Java程式語言支援哪八種基本資料類型?

字元串由類        表示。

7.      是固定數目的單一資料類型值的容器對象。

練習

建立一個小程式,在其中定義一些字段。試着建立一些非法的字段名,看看編譯器會報哪種類型的錯誤。參考命名規則和約定。

在上題建立的程式中,試着不初始化一些字段并輸出它們的值。試着不初始化局部變量看看編譯器會報什麼錯。熟悉常見的編譯器錯誤有助于識别程式bug。

答案

相關答案參考