名字是編程的基礎(chǔ)。在程序中,名字被用來指代許多不同種類的東西。若要使用這些東西,程序員必須理解命名規(guī)則,正確使用這些名字的規(guī)則??偠灾?,程序員必須了解語法和名字的語義。
根據(jù) Java 的語法規(guī)則,最基本的名字是標(biāo)識符。標(biāo)識符可以用于命名類、 變量和方法。標(biāo)識符是一個或多個字符序列。它必須以字母或下劃線開頭,必須完全由字母、 數(shù)字和下劃線組成。(“下劃線”指的是字符’_'。)例如,這里是一些正確的標(biāo)識符:N n rate x15 quite_a_long_name HelloWorld
標(biāo)識符中不允許有空格 ;HelloWorld 是合法的標(biāo)識符,但是”Hello World”不是。相同字母大小寫是不同的意義,所以 HelloWorld、 helloworld、 HELLOWORLD 和 hElloWorLD 都是不同的名字。某些詞語在 Java 中作為保留字,具有特殊用途,不能用作標(biāo)識符。這些詞語包括:class、 public、 static、 if、 else、 while 和其它幾十個詞。(記住保留字不是標(biāo)識符,所以它們不能作為名字使用。)
Java 對于什么才算作字母或數(shù)字實際上相當(dāng)自由的。Java 使用 Unicode 字符集,其中包括成千上萬個字符,這些字符來自許多不同的語言和不同的字母表,許多字符被當(dāng)作字母或數(shù)字。然而,實際輸入的還是依賴于常規(guī)的英文鍵盤。
命名的語用學(xué)包括指導(dǎo)如何選擇事物名字的風(fēng)格。例如,為類(Class)命名習(xí)慣以大寫字母開頭,而變量和方法名以小寫字母開頭;在你自己的程序中按照這樣的約定命名,可以避免很多不必要的麻煩。盡管有些類型的變量名是以下劃線開頭的,但是大多數(shù) Java 程序員在名字中不使用下劃線。當(dāng)一個名稱由多個詞語組成,像 HelloWorld 或 interestRate,大家習(xí)慣第一個單詞以外的每個單詞首字母大寫;這被稱為駝峰式大小寫,因為在名字中的大寫字母看起來像一個駱駝背上的駝峰。
最后我要指出的是,除了簡單的標(biāo)示符外,在 Java 中有一些復(fù)雜的東西,我們可以用幾個簡單的詞語組成復(fù)合詞來表示,并由句點分隔開。(復(fù)合名也是合格的名字。)你已經(jīng)見過這樣一個例子了: System.out.println。這里的想法是, Java 中的某些事物能包含其它東西。復(fù)合名是一種路徑,可以表示一層或多層包含關(guān)系。System.out.println 表示“System” 包含“out”,“out”又包含“println”。
程序能操作存儲在內(nèi)存中的數(shù)據(jù)。在機(jī)器語言中,數(shù)據(jù)只是存儲數(shù)據(jù)的內(nèi)存地址。像 Java 一樣的高級語言,名字代替地址以指代數(shù)據(jù)。跟蹤數(shù)據(jù)實際存儲在內(nèi)存中的位置是計算機(jī)的工作。程序員只需要記住名字。使用這種方式 ——一個名字指向內(nèi)存中數(shù)據(jù),這就叫一個變量。
變量實際上是相當(dāng)微妙的。嚴(yán)格地說,一個變量不是數(shù)據(jù)本身,而是內(nèi)存中保存數(shù)據(jù)的位置。應(yīng)該把一個變量看成一個容器或盒子,里面存放稍后需要使用的數(shù)據(jù)。變量直接指向盒子,間接的指向盒子中的數(shù)據(jù)。既然盒子中的數(shù)據(jù)能夠改變,那么在程序執(zhí)行期間,變量能夠在不同的時間指向不同的數(shù)據(jù)值,但是始終指向同一個盒子。對于初學(xué)程序員,這可能會有些困惑,因為在程序中,以不同方式使用變量時會有所不同,有時候它指向容器,但換其它方式使用時,它指的是容器中的數(shù)據(jù)。下面你會看到這兩種情況的例子
(在這種方式中,變量就像標(biāo)題,舉個例子——“美國總統(tǒng)”。這個標(biāo)題在不同的時候可能指不同的人,但是總是指同一個官職。如果我說“總統(tǒng)正在打籃球”,我的意思是奧巴馬在打籃球。但是如果我說“希拉里想當(dāng)總統(tǒng)”,我的意思是她想競選那個官職,而不是她想變成奧巴馬。)
在 Java 中,只有一種方式將數(shù)據(jù)導(dǎo)入到變量中,那就是將數(shù)據(jù)放到該變量名的盒子中,即賦值語句。賦值語句就像下面這樣:
1 | variable = expression; |
表達(dá)式可以指向任何值,或計算值。當(dāng)計算機(jī)執(zhí)行程序的過程中進(jìn)行一個賦值語句操作,它會對表達(dá)式求值并將結(jié)果賦給變量。看看下面一個簡單的賦值語句:
1 | rate = 0.07 |
此賦值語句中的變量是 rate,表達(dá)式的值是0.07。計算機(jī)執(zhí)行此賦值語句就是將數(shù)值0.07放到變量 rate 中,不論 rate 之前存的是什么值都會被覆蓋掉?,F(xiàn)在,考慮下面更復(fù)雜的賦值語句,稍后可能會在同一個程序中出現(xiàn):
1 | interest = rate * principal; |
“rate principal” 表達(dá)式的值被賦給了 interest 變量。在這個表達(dá)式中, 符號 是一個乘法算子,告訴計算機(jī)將 rate 和 principal 相乘。rate 和 principal 都是以自身含義所命名的變量,真正被乘的是存在變量中的值。當(dāng)一個變量在表達(dá)式中使用,應(yīng)該關(guān)注存在該變量中的值。 在這種情況下,變量似乎是指“盒子”中的數(shù)據(jù),而不是“盒子”本身。當(dāng)計算機(jī)執(zhí)行這條賦值語句時,將 rate 的值乘以 principal 的值,然后將答案存放到 interest 指向的“盒子”中。當(dāng)一個變量被用在賦值語句的左邊,它指向該變量名的“盒子”。
(注意,順便說一下,一條賦值語句是一個命令,在某個時間由計算機(jī)執(zhí)行。這不是語句的全部(這句不太理智是什么意思)。例如,假設(shè)一個程序包含語句“rate = 0.07;”。如果“interest = rate * principal;”語句后來在程序中執(zhí)行,我們能說 principal 乘以0.07么?當(dāng)然不能!rate 的值可能同時被另外一個語句改變。雖然都是使用“=”符號,但賦值語句的含義和數(shù)學(xué)中的等式是完全不一樣的。)
Java 中的變量被設(shè)計為僅保存一個特定類型的數(shù)據(jù)。它可以合法持有該類型的數(shù)據(jù),其它類型則不行。如果你試圖違反本規(guī)則,分配給一個變量錯誤類型的數(shù)據(jù),編譯器會認(rèn)為這是一個語法錯誤。我們說Java是強類型語言,因為它強制執(zhí)行此規(guī)則。
Java 中有8個內(nèi)置的原始數(shù)據(jù)類型。這些類型為 byte、 short、int、long、float、double、char和 boolean。前四種類型保留整數(shù)(如17,-38477,0)。這四個整數(shù)類型由他們可以容納的整數(shù)范圍區(qū)分。浮點和雙精度浮點類型可以保存實數(shù)(如3.6和-145.99)。其實,兩個實數(shù)類型以范圍和精度區(qū)分。char 類型的變量可以存放一個 Unicode 字符集中的字符。布爾類型的變量可以持有一個邏輯值 TRUE(真)或 FALSE(假)。
在計算機(jī)內(nèi)存中的任何數(shù)據(jù)值,都必須以二進(jìn)制數(shù)表示,即0和1的字符串。單個0或1被稱為位(bit)。8個位的串被稱為一個字節(jié)(byte)。內(nèi)存中通常以字節(jié)為單位。毫不奇怪,byte 數(shù)據(jù)類型指的就是存儲器的單個字節(jié)。byte 類型的變量可以存放一個8個位的字符串,它可以表示一個大于等于-128,小于等于127之間的整數(shù)。(該范圍內(nèi)總共有256個整數(shù),8位能表示256,2個8次冪等不同的值。)其它的整數(shù)類型,
不必記住這些數(shù)字,但是大致的范圍你需要了解。通常情況下,表示整數(shù)使用int類型就足夠了。
float 類型占用存儲器中4個字節(jié),使用標(biāo)準(zhǔn)編碼的實數(shù)。float 類型最大值為10的38次方,精確到小數(shù)點后7位。(32.3989231134和32.3989234399兩者都可以存儲在float類型中,不過要四舍五入至32.398923。) double類型占用8個字節(jié),可以達(dá)到10的308次方,精確到小數(shù)點后15位。通常,你應(yīng)該使用double類型來保存實際的值。
char 類型的變量在儲存器中占2個字節(jié)。字符型變量的值可以是單個字符,如 A、*、x、或者一個空格。也可以是一個特殊的字符,如制表符(tab)或回車或來自不同語言的 Unicode 字符之一。char 類型的值和整數(shù)值是密切相關(guān)的,實際上一個字符是以一個16位的整數(shù)編號存儲的。 事實上,在某些情況下 Java 中的字符被當(dāng)成整數(shù)來使用。
要記住原始類型的值是有位數(shù)限制的。所以,一個 int 類型不能是任意整數(shù),它只能是限定范圍內(nèi)的整數(shù)。同樣,float 和 double 只能取一定范圍內(nèi)的值。它們不是數(shù)學(xué)意義上的真實數(shù)。例如,數(shù)學(xué)常數(shù) π 只能使用 float 或 double 類型取近似值, 因為 π 有無限個小數(shù)位。類似的1/3也只能用 float 和 double 來近似的表示。
數(shù)據(jù)值以比特位(bit)序列存儲在計算機(jī)中。在計算機(jī)內(nèi)存中看起來不像是有任何價值的東西。在你寫的程序中,你需要一種方法來包含一個常量值。程序中,你需要的常量值為文字。文字就是你在程序中輸入的值。它只是一種常量的名稱。
例如,在程序中輸入一個 char 類型的值,你必須用一對單引號包括它,比如 ‘A’、’‘、’x'。字符和引號共同組成了一個 char 類型的值。沒有引號的話,A 就成了一個標(biāo)識符,也會被看作是一個乘號。引號不是值的一部分,也不會存在變量當(dāng)中。只是命名一個特定的字符常量的約定。如果你想將字符 A 存儲在 char 類型變量 ch 中,可以用賦值語句這樣做
1 | ch = 'A' ; |
某些字符串中包含特殊字符時就必須使用“轉(zhuǎn)義字符”,反斜杠“”。特別是像這樣的,tab 表示 ‘t’,回車是 ‘r’,換行是 ‘n’,單引號是 ”,反斜杠就是它本身 ”。請注意,即使在 ‘t’ 引號內(nèi)輸入兩個字符,這個值還是表示一個 tab 。
數(shù)值可能比你想象的要復(fù)雜。當(dāng)然也有很簡單的,像 317 和 17.42 這樣的。但是在 Java 程序中也有其它的數(shù)值需要表示的。首先,實數(shù)可以用指數(shù)的形式表示,如 1.3e12 或 12.3737e-108?!癳12” 和 “e-108” 表示 10 的冪,所以 1.3e12 表示 1.3 倍 10 的 12 次冪,12.3737e-108 表示 12.3737 倍 10 的 -108 次冪。這種格式可以用來表示非常大和非常小的數(shù)。任何包含小數(shù)點或者指數(shù)的數(shù)字值是 double 類型的。為了區(qū)分 float 類型的值,你必須要在數(shù)字值的后面追加一個“F”或“f”。例如,“1.2F”表示這是一個 float 類型的值。(因為 Java 規(guī)則就是這樣規(guī)定的,你不能將一個 double 類型的值賦給一個 float 類型的變量,所以可能你會犯一個比較搞笑的錯誤,如果你寫了一個這樣的語句“x = 1.2;”,x 是 float 類型的,其實這是錯誤的。你必須這樣寫“x = 1.2f;”。這就是為什么我堅持推薦使用 double 類型來保存實數(shù)的原因了。)
即使是整型值,也有比較復(fù)雜的。普通的整數(shù),如 177777 和 -32 可以是 byte 、 short 或 int 類型的值,這取決于它們的大小。你可以加上后綴“L”來聲明一個 Long 類型的值。例如:17L 或 728476874368L。另一個復(fù)雜的問題是 Java 支持二進(jìn)制、八進(jìn)制、十六進(jìn)制值。我不想詳細(xì)的講解有關(guān)進(jìn)制數(shù)的東西,但萬一在其它人的程序中碰到了進(jìn)制數(shù),你應(yīng)該了解一些相關(guān)的知識。八進(jìn)制數(shù)字只有 0 到 7。在 Java 中,以 0 開頭的數(shù)字值被解釋為八進(jìn)制數(shù);例如,八進(jìn)制值 045 代表 37,不是數(shù)字 45 。八進(jìn)制數(shù)很少使用,但必須要注意那些以0開頭的數(shù)值。十六進(jìn)制數(shù)字使用 16 位數(shù)字,數(shù)字 0 到 9 和字母 A、 B、 C、 D、 E 和 F。這種情況下,字母大小寫是不敏感的。字母表示 10 到 15 的數(shù)字。在 Java 中,十六進(jìn)制字符串以 0x 或 0X 開頭,如 0×45 或 0xFF7A。最后,二進(jìn)制數(shù)以 0b 或 0B 開頭, 只能包含數(shù)字 0 和 1,例如: 0b10110。
最后一個麻煩, Java 7 的數(shù)值文本可以包含下劃線 (“_”),可以用于分隔數(shù)字進(jìn)行分組。例如,70 億可以寫成 7_000_000_000,這比 7000000000 好理解多了。沒有關(guān)于多少位數(shù)必須分組的規(guī)則。下劃線對于長二進(jìn)制數(shù)也特別有用。例如,0b1010_1100_1011。
十六進(jìn)制數(shù)字也可以用來表示任意的 Unicode 字符。一個 Unicode 字符可以由 u 跟著四個十六進(jìn)制數(shù)字組成。例如, ‘u00E9′ 表示是帶重音符的”e” Unicode 字符。
對于布爾(boolean)類型,只有兩個值: true 和 false。直接輸入這些詞,不帶引號,就像現(xiàn)在輸入的那樣,不過它們代表的是值,不是變量。布爾值常發(fā)生在條件表達(dá)式中。例如,
1 | rate > 0.05 |
如果 rate 的值大于 0.05 那么表達(dá)式的結(jié)果為真(true),如果 rate 的值小于 0.05 那么結(jié)果為假(false)。你會看到第 3 章中,布爾值的表達(dá)式在控制結(jié)構(gòu)中廣泛使用。當(dāng)然,布爾值也可以被賦值給布爾(boolean)類型的變量。例如, test 是一個布爾類型變量,下面的賦值語句都是正確的:
1 2 | test = true ; test = rate > 0.05 ; |
除了原始類型 Java 還有其它類型,但所有其它類型都是對象,而不是“原始”數(shù)據(jù)值。大多數(shù)情況下,我們不關(guān)心臨時對象。然而有一個預(yù)定義的對象類型是非常重要的! String 類型。 (String 是一種類型,但不是原始類型; 事實上是類的名稱,下一節(jié)我們會著重說說 String 類型。)
String類型的值是一個字符序列。你已經(jīng)看到了一個字符串:“Hello World!”。雙引號里面的就是了,它們在程序中輸入。然而,它們并不是真正的字符串值,其中包括剛剛引號之間的一部分。一個字符串,可以包含任意數(shù)目的字符,甚至是零。沒有內(nèi)容的字符串被稱為空字符串,由“”表示,一對雙引號之間沒有任何內(nèi)容。記住單引號和雙引號的區(qū)別!單引號用于字符而雙引號用于字符串!那就是字符串 “A” 和字符 ‘A’ 之間的巨大差異。
在字符串文本中,可以使用反斜杠符號表示特殊字符。在這里,雙引號本身就是一個特殊字符。例如,若要表示的字符串值 I said, “Are you listening!” 而且以換行結(jié)尾,那就必須鍵入字符串:”I said, “Are you listening!”n” 你也可以使用 t、r、和 u00E9 這樣的 Unicode 序列來表示字符串中的其它特殊字符。
程序中變量第一次使用才需要聲明。變量聲明語句用來聲明一個或多個變量,并給它們起名字。當(dāng)計算機(jī)執(zhí)行變量聲明時,它一邊給該變量分配內(nèi)存,并將內(nèi)存與該變量名稱關(guān)聯(lián)起來。簡單的變量聲明形式:
type-name variable-name-or-names;類型名稱 變量名或名稱;
variable-name-or-names(變量名或名稱)可以是單個變量名或以逗號分隔的變量名的列表。(稍后我們會看到比這更復(fù)雜一些的變量聲明語句。)良好的編程風(fēng)格是在聲明語句中只寫一個變量,除非變量之間有某種關(guān)系。例如:
1 2 3 4 5 | int numberOfStudents; String name; double x, y; boolean isFinished; char firstInitial, middleInitial, lastInitial; |
在每個變量聲明后說明在程序中的目的,或者提供一些其它信息給后面有可能需要閱讀這些代碼的人,這也是良好的編程風(fēng)格。例如:
1 2 | double principal; // Amount of money invested. double interestRate; // Rate as a decimal, not percentage. |
在本章中,我們只在程序的 main() 方法中聲明變量。方法內(nèi)聲明的變量稱為該方法的局部變量。它們只存在方法中,當(dāng)它在運行時,外部無法訪問。 變量聲明可以在方法中的任何地方,不過要在使用之前聲明。有些人喜歡在方法的開頭聲明所有變量。有些人就在需要的時候才聲明。我的建議:將所有重要的變量在開頭聲明,并使用注釋,說明每個變量的目的。對于程序整體邏輯來說不重要的“臨時變量 ”,推薦在第一次使用的地方聲明它們。下面是一個簡單的程序示例,使用了一些變量和賦值語句:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | /** * This class implements a simple program that * will compute the amount of interest that is * earned on $17,000 invested at an interest * rate of 0.027 for one year. The interest and * the value of the investment after one year are * printed to standard output. */ public class Interest { public static void main(String[] args) { /* Declare the variables. */ double principal; // The value of the investment. double rate; // The annual interest rate. double interest; // Interest earned in one year. /* Do the computations. */ principal = 17000; rate = 0.027; interest = principal * rate; // Compute the interest. principal = principal + interest; // Compute value of investment after one year, with interest. // (Note: The new value replaces the old value of principal.) /* Output the results. */ System.out.print( 'The interest earned is $' ); System.out.println(interest); System.out.print( 'The value of the investment after one year is $' ); System.out.println(principal); } // end of main() } // end of class Interest |
這個程序調(diào)用了幾個方法向程序的用戶顯示信息。使用了兩個不同的方法:System.out.print 和 System.out.println。之間的區(qū)別是 System.out.println 在顯示的信息后面增加了換行,而 System.out.print 則沒有。因此在同一行顯示字符串是調(diào)用 System.out.print 語句, interest 的值是由 “System.out.println(interest);” 這一句顯示的。需要注意的是由 System.out.print 或 System.out.println 顯示的值是由方法名后的括號中提供的。這個值被稱為方法的參數(shù)。參數(shù)提供方法執(zhí)行其任務(wù)所需的信息。在調(diào)用方法時,所有參數(shù)都列在方法名后括號內(nèi)。如果在一個方法沒有參數(shù),方法名后面必須跟一對空括號。
這本書上所有的示例程序在 http://math.hws.edu/javanotes/source 上都能找到源代碼。在該網(wǎng)站的下載文檔中也有,在 source 文件夾中。例如, Interest 程序的源代碼,可以在 source 文件夾 chapter2 子文件夾中找到 Interest.java 文件。