Java學習(一).Java基礎
?
1、標識符
??? Java語言的字符使用Unicode編碼標準。Unicode字符集中的每個字符為16位編碼。這樣,Java語言的字符就不僅可以表示常用的ASCII字符,即數字0~9、英文字母A~Z、a~z以及+、-、*、/等常用符號,還可以表示如漢字、拉丁語、希臘語等其他語言文字。
??? 標識符是由字母、數字、下劃線(_)、美元符($)組成的、必須以字母、下劃線或美元符開頭的、字符個數有限的字符序列。如i、count、myStack、GetValue、_length等都是合法的標識符。Java語言在定義標識符時,其字母符號區分大小寫(或稱是大小寫敏感的),所以count、Count、COUNT表示不同的標識符。標識符可以用來命名變量名、常量名、類名等。
??? Java語言中有固定含義的標識符稱作關鍵字。用戶不允許用關鍵字定義標識符。Java語言中的關鍵字共有47個,如下表所示。
abstract ? boolean? ? break?? ???? byte? ??? case? ???? catch
char? ???? class? ??? continue? ?? default ? do?? ????? double
else? ???? extends? ? false?? ???? final? ?? finally ?? float
for?? ???? if?? ????? implements? import? ? instanceof int
interface long? ???? native?? ??? new?? ??? null? ???? package
private? ? protected public?? ??? return? ? short? ??? static
super? ??? switch? ?? synchronized this? ??? throw? ??? throws
transient true? ???? try??? ????? void? ??? while
注:goto也是保留的關鍵字,雖然不能在java中使用
?
2、變量和常量
??? 程序通常要處理數據,處理數據首先要保存數據。程序中要保存的數據都需要系統分配內存空間。變量和常量都需要系統分配內存空間。
變量:
??? 變量是一個保存數據的內存區域的名字。變量在使用時必須先定義(或稱聲明),然后才能用賦值語句(或其他形式)來為其賦值。
??? 變量定義是指示編譯器為特定數據類型的數值保存在內存中分配適當的內存空間。這樣,在隨后的程序中就可以用賦值語句(或其他形式,如在變量定義時直接給出初始值)為該變量賦值。變量名的命名必須符合2.1節所說的標識符的命名規定。
??? 變量聲明的格式為:
??? <數據類型名><變量名表>;
??? 隨著程序規模的擴大,經常是多人合作完成一個程序的編寫。為了防止變量使用的混亂,變量的使用范圍是受限的,每個變量只在自己的使用范圍內有效。變量的使用范圍稱作變量的作用域。變量的使用范圍是定義該變量的程序塊。
?
【例2.1】關于變量作用域的示例
public class Example2_1
{
??? public static void main(String args[])
??? {
??????? int i = 10, j;
??????? j? = 20;
???????? {
??????????? int k = 100;
??????????? System.out.println("k = " + k );
??????? }
//????? System.out.println("i = " + i + "? j = " + j + "??? k = " + k);
??????? System.out.println("i = " + i + "? j = " + j );
??? }
}
程序運行結果:
k = 100
i = 10 j = 20
??? 程序說明:
??? 在main函數中,定義了int類型的變量i和j,變量i在定義時給了初始化值10,變量j隨后用賦值語句賦了數值20。在此程序塊中,輸出語句輸出了變量i和j的當前數值。在下一層程序塊(即下一層的花括號所括的范圍)內,又定義了int類型的變量k,由于此變量k的作用范圍只限于下一層程序塊內,所以輸出語句中如果包括了變量k(即如果使用了注釋掉的語句),則編譯器將指示錯誤。
??? 在程序設計中,例子中所示的程序塊形式并不多見。常見的程序塊形式是if語句、while語句、for語句等后面跟隨的一對花括號。以此類推,可以知道,在一個函數中定義的變量只在該函數內有效。
常量:
??? 在程序設計中,有時需要定義一個變量,并要求該變量在整個程序運行期間保持不變,這種在整個程序運行期間保持不變的變量稱作常量。常量也是一種標識符,所以定義常量時也要符合標識符的規定。
??? 定義常量的方法是在定義變量的語句最前面加上關鍵字final。
??? 和變量類同,常量定義也是指示編譯器為特定數據類型的數值保存在內存中分配適當的內存空間。常量和變量惟一的不同之處是,常量只允許在定義時給出其數值,并不允許在隨后的程序中改變其數值。在習慣上,常量名通常為全大寫字母。例如:final int MAXSIZE = 100; 就定義了常量MAXSIZE等于100。
?
?
3、基本數據類型
??? 數據類型規定了一類數據的數據位長度(或稱字符個數)、取值范圍以及對該類數據所能進行的操作。
??? Java語言中共定義了8種基本數據類型,其中4種為整型數,2種為浮點型數,1種為字符型數,1種為布爾型數。數據類型不同,所定義的變量占用的內存空間、取值范圍以及對該類數據所能進行的操作也不同。
??? Java語言定義的8種基本數據類型及相應的關鍵字如下:
? 整? 型:byte 、short、 int、 long
? 浮點型:float、double
? 邏輯型:boolean
? 字符型:char
1.整型
??? 整型數是零和有限范圍的正整數和負整數。由于4種不同整型數的數據位不同,所以相應的正整數和負整數的范圍也不同。
??? Java的整數類型
??? 類型 ??????? 數據位 ??? 數值范圍
??? 字節型byte ? 8 bits ??? -128——127(即-2^7——2^7-1)
??? 短整型short 16 bits ??? -32768——32767(即-2^15——2^15-1)
??? 整? 型int ?? 32 bits ??? -2147483648——2147483647(即-2^31——2^31-1)
??? 長整型long ? 64 bits ??? -9223372036854775808——9223372036854775807(即-2^63——2^63-1)
??? Java的整型數可以表示為十進制、八進制或十六進制。具體表示方法為:
? 十進制:用若干個0~9之間的數字表示,并規定首位不能為0,如123。
? 八進制:以0打頭,后跟若干個0~7之間的數字,如0123。
? 十六進制:以0x或0X打頭,后跟若干個0~9之間的數字以及a~f之間的小寫字母或A~F之間的大寫字母,a~f或A~F分別表示數值10~15,如0X123E。
??? 注:字面值是在程序中用到的顯式數據值,如123就是一個字面值。
??????? Java語言規定,所有的整型字面值都隱含為int型。
??????? 若要將一個整數字面值明確地表示為long型時,需在后面加L或l,如21474836470L或12345l。
2.浮點型
??? 浮點型數由整數部分和小數部分組成。浮點型數用來表示實數。浮點數有兩種表示方式:
? 標準記數法:由整數部分、小數點和小數部分構成。如123.123,123.0。
? 科學記數法:由整數、小數點、小數和指數部分構成,指數部分由一個e或E后跟帶正負號的整數表示。如123.123用科學記數法可表示為1.23123E+2。需要注意的是,科學記數法中,一個浮點型數的整數部分不一定是小數點前的整數。
??? 浮點型數可以表示精度很高的或帶有小數部分的數值。當一個變量要保存此類數值時,該變量必須定義為浮點型變量。
??? Java語言的浮點型有float和double兩種。浮點數類型的類型、數據位和數值范圍如下:
??? Java的浮點數類型
??? 類型 ?????????? 數據位 ? 數值范圍
??? 單精度浮點float ? 32 bits ? 3.4e-038——3.4e+038
??? 雙精度浮點double 64 bits ? 1.7e-308——1.7e+308
??? Java語言規定,所有的浮點型字面值都隱含為double型。若要將一個浮點型字面值明確地表示為float型時,需在后面加F或f,如123.123F或1.23123E+2f。
??? 在定義變量時,對于整型變量或浮點型變量,要認真分析變量可能的取值范圍,并選擇合適的數據類型來定義變量,以免造成內存空間浪費,或由于超出數值范圍或數值精度不夠而造成出錯。例如,如果一個變量的取值為確定的1到1000,則該變量應定義成short類型。又例如,如果一個變量的可能取值無法準確估計,則應按該變量可能的最大數值、并保留相當的寬裕程度來選擇該變量的數據類型。
?
3.邏輯型
???
邏輯型用來定義保存邏輯值的變量。邏輯型也稱為布爾型。邏輯值只有真(true)和假(false)兩個值。
??? 所有邏輯運算(如a<b)的運算結果值都是邏輯值,如當a = 4,b = 6時,邏輯運算a<b的結果值就是true。
??? 邏輯型數值主要用在流程控制語句中的條件表達式,如if、while、for等語句的條件表達式都是邏輯型數值。
?
4.字符型
???
Java語言中,一個Unicode標準下的編碼稱作一個字符。Unicode標準用16位編碼表示一個字符。字符型用來表示字符型變量和字符型字面值。
??? Java語言中,字符型字面值用一對單引號括起來,如'a'、'A'、'#'等都是字符型字面值。由于一些控制字符不能在屏幕上直接顯示,以及字符串中特殊符號的表示等問題,需要有特殊方法表示這些符號。不能直接顯示的控制字符字面值、或字符串中特殊符號表示使用轉義字符的表示方法。
??? 轉義字符類型
??? 轉義字符 ? 含義
??? \n ??????? 換行,將光標移至下一行的開始
??? \t ??????? 水平制表,將光標移至下個制表符位置
??? \r ??????? 回車,將光標移至當前行的開始
??? \\ ??????? 反斜杠,輸出一個反斜杠
??? \’ ?????? 單引號,輸出一個單引號
??? \” ?????? 雙引號,輸出一個雙引號
??? 如系統標準輸出語句System.out.print()表示輸出字符串后不換行,下面的輸出語句:
??? System.out.print("Hello!\n");表示輸出字符串"Hello!"后換行。
?
?
4、賦值語句
??? 賦值語句的語法形式是:
??? <變量> = <表達式>;
??? 賦值語句中,等號(稱作賦值號)是賦值語句的標識,<表達式>可以是一個常量,或另一個已賦過值的變量,或是由運算符組成的一個表達式。是把一個常量或另一個已賦過值的變量中的數值賦給另一個變量。當一個變量被用賦值語句重新賦值時,該變量原先的賦值就被沖掉了,即該變量原先的賦值就沒有了。
??? Java語言是一種強類型語言,所謂強類型語言是指數據類型的匹配要求十分嚴格。如果一個表達式的數據類型不一致等問題出現,則編譯器給出類型不一致的出錯信息。關于賦值語句的類型匹配有以下兩種情況:
??? (1)類型相同。類型相同是指賦值號左端的數據類型和賦值號右端的數據類型完全一致。此種情況可以正確賦值。例如:
???????? int smallValue =100;?? //類型相同
???????? long bigValue ? = 100L;?? //類型相同
??? (2)類型兼容。類型兼容是指賦值號左端的數據類型比賦值號右端的數據類型長。此時系統會自動將賦值號右端的數據類型轉化成和賦值號左端一樣的數據類型。這里所說的數據類型長,是指數據類型的位數長,如long類型就比int類型的位數長。例如:
???????? long bigval = 100;?? //100是int類型,將自動轉化為100L
???????? double x = 12.345F;?? //12.345F是float類型,將自動轉化為12.345
??? (3)類型不兼容。若賦值號右端的數據類型比賦值號左端的數據類型長則類型不兼容。此時系統在編譯時會產生“可能存在精度損失”的編譯錯誤。例如:
???????? int smallValuel = 100L;? // 100L 是long類型,不兼容
???????? float x = 12.345;???? ?? //12.345是double類型,不兼容
??? 當出現類型不兼容錯誤時,有兩種解決方法:
? 重新定義賦值號左端變量的數據類型,使之變成滿足要求的較長的數據類型。
? 用強制類型轉換方法把賦值號右端的數據類型轉換成和賦值號左端相同的數據類型。但要注意,強制類型轉換可能丟失數據或損失數據的精度。
??? 強制類型轉換的格式為:
??? (<目標類型>)<表達式>
??? 例如:
??? int i;
??? long k = 100L;
??? i = (int) k;??? //把變量k中的數值強制轉換成int類型后賦給變量i
?
5、運算符和表達式
??? 在Java語言之前,C語言和C++語言是最為廣泛使用的高級程序設計語言,為了使Java語言能盡快被程序設計人員接受,Java語言設計者采用了把基本關鍵字和基本語句設計成和C/C++語言相同形式的方法。因此,對于已經掌握C\C++語言的人來說,Java語言在基本關鍵字、運算符、表達式、賦值語句、流程控制語句等方面,是和C/C++語言基本相同的。
???
Java的運算符可分為4類:算術運算符、關系運算符、邏輯運算符和位運算符。
?
1.算術運算符
???
Java的算術運算符分為一元運算符和二元運算符。一元運算符只有一個操作數;二元運算符有兩個操作數,運算符位于兩個操作數之間。算術運算符的操作數必須是數值類型。
???
(1)一元運算符:
??? 一元運算符有:正(+)、負(-)、加1(++)和減1(--)4個。
??? 加1、減1運算符只允許用于數值類型的變量,不允許用于表達式中。加1、減1運算符既可放在變量之前(如++i),也可放在變量之后(如i++),兩者的差別是:如果放在變量之前(如++i),則變量值先加1或減1,然后進行其他相應的操作(主要是賦值操作);如果放在變量之后(如i++),則先進行其他相應的操作,然后再進行變量值加1或減1。
??? 例如:
??? int i=6,j,k,m,n;
??? j = +i;??? //取原值,即j=6
??? k = -i;??? //取負值,即k=-6
??? m = i++;??? //先m=i,再i=i+1,即m=6,i=7
??? m = ++i;??? //先i=i+1,再m=i,即i=7,m=7
??? n = j--;??? //先n=j,再j=j-1,即n=6,j=5
??? n = --j;??? //先j=j-1,再n=j,即j=5,n=5
??? 在書寫時還要注意的是:一元運算符與其前后的操作數之間不允許有空格,否則編譯時會出錯。
???
(2)二元運算符
??? 二元運算符有:加(+)、減(-)、乘(*)、除(/)、取余(%)。其中+、-、*、/完成加、減、乘、除四則運算,%是求兩個操作數相除后的余數。
?
??? %求余操作舉例:
??? a % b = a - (a / b) * b
??? 取余運算符既可用于兩個操作數都是整數的情況,也可用于兩個操作數都是浮點數(或一個操作數是浮點數)的情況。當兩個操作數都是浮點數時,例如7.6 % 2.9時,計算結果為:7.6 - 2 * 2.9 = 1.8。
??? 當兩個操作數都是int類型數時,a%b的計算公式為:
??? a % b = a - (int)(a / b) * b
??? 當兩個操作數都是long類型(或其他整數類型)數時,a%b的計算公式可以類推。
??? 當參加二元運算的兩個操作數的數據類型不同時,所得結果的數據類型與精度較高(或位數更長)的那種數據類型一致。
?
??? 例如:
??? 7 / 3?? ? //整除,運算結果為2
??? 7.0 / 3?? //除法,運算結果為2.33333,即結果與精度較高的類型一致
??? 7 % 3?? ? //取余,運算結果為1
??? 7.0 % 3?? //取余,運算結果為1.0
??? -7 % 3?? //取余,運算結果為-1,即運算結果的符號與左操作數相同
??? 7 % -3?? //取余,運算結果為1,即運算結果的符號與左操作數相同
2.關系運算符
???
關系運算符用于比較兩個數值之間的大小,其運算結果為一個邏輯類型的數值。關系運算符有六個:等于(==)、不等于(!=)、大于(>)、大于等于(>=)、小于(<)、小于等于(<=)。
?
??? 例如:
??? 9 <= 8?? ?? //運算結果為false
??? 9.9 >= 8.8? //運算結果為true
??? 'A' < 'a' ? //運算結果為true,因字符'A'的Unicode編碼值小于字符'a'的
??? 要說明的是,對于大于等于(或小于等于)關系運算符來說,只有大于和等于兩種關系運算都不成立時其結果值才為false,只要有一種(大于或等于)關系運算成立其結果值即為true。例如,對于9 <= 8,9既不小于8也不等于8,所以9 <= 8 的運算結果為false。對于9 >= 9,因9等于9,所以9 >= 9的運算結果為true。
?
3.邏輯運算符
???
邏輯運算符要求操作數的數據類型為邏輯型,其運算結果也是邏輯型值。邏輯運算符有:邏輯與(&&)、邏輯或(||)、邏輯非(!)、邏輯異或(^)、邏輯與(&)、邏輯或(|)。
??? 真值表是表示邏輯運算功能的一種直觀方法,其具體方法是把邏輯運算的所有可能值用表格形式全部羅列出來。Java語言邏輯運算符的真值表如下:
??? 邏輯運算符的真值表
??? A ???? B ???? A&&B ? A||B? !A ??? A^B ?? A&B ?? A|B
??? false false false false true ? false false false
??? true ? false false true false true ? false true
??? false true ? false true true ? true ? false true
??? true ? true ? true ? true false false true ? true
??? 前兩列是參與邏輯運算的兩個邏輯變量,共有4種可能,所以表2.5共有4行。后6列分別是6個邏輯運算符在邏輯變量A和邏輯變量B取不同數值時的運算結果值。
??? 要說明的是,兩種邏輯與(&&和&)的運算規則基本相同,兩種邏輯或(||和|)的運算規則也基本相同。其區別是:&和|運算是把邏輯表達式全部計算完,而&&和||運算具有短路計算功能。所謂短路計算,是指系統從左至右進行邏輯表達式的計算,一旦出現計算結果已經確定的情況,則計算過程即被終止。對于&&運算來說,只要運算符左端的值為false,則因無論運算符右端的值為true或為false,其最終結果都為false。所以,系統一旦判斷出&&運算符左端的值為false,則系統將終止其后的計算過程;對于 || 運算來說,只要運算符左端的值為true,則因無論運算符右端的值為true或為false,其最終結果都為true。所以,系統一旦判斷出|| 運算符左端的值為true,則系統將終止其后的計算過程。
?
??? 例如,有如下邏輯表達式:
??? (i>=1) && (i<=100)
??? 此時,若i等于0,則系統判斷出i>=1的計算結果為false后,系統馬上得出該邏輯表達式的最終計算結果為false,因此,系統不繼續判斷i<=100的值。短路計算功能可以提高程序的運行速度。
??? 作者建議讀者:在程序設計時使用&&和||運算符,不使用&和|運算符。
??? 用邏輯與(&&)、邏輯或(||)和邏輯非(!)可以組合出各種可能的邏輯表達式。邏輯表達式主要用在 if、while等語句的條件組合上。
??? 例如:
??? int i = 1;
??? while(i>=1) && (i<=100) i++;??? //循環過程
??? 上述程序段的循環過程將i++語句循環執行100次。
?
4.位運算符
???
位運算是以二進制位為單位進行的運算,其操作數和運算結果都是整型值。
??? 位運算符共有7個,分別是:位與(&)、位或(|)、位非(~)、位異或(^)、右移(>>)、左移(<<)、0填充的右移(>>>)。
??? 位運算的位與(&)、位或(|)、位非(~)、位異或(^)與邏輯運算的相應操作的真值表完全相同,其差別只是位運算操作的操作數和運算結果都是二進制整數,而邏輯運算相應操作的操作數和運算結果都是邏輯值。
?
??? 位運算示例
?? 運算符 ?名稱 ? 示例 ?? 說明
??? & ????? 位與 ?? x&y ??? 把x和y按位求與
??? | ????? 位或 ?? x|y ??? 把x和y按位求或
??? ~ ????? 位非 ?? ~x ???? 把x按位求非
??? ^ ????? 位異或 x^y ??? 把x和y按位求異或
??? >> ???? 右移 ?? x>>y ?? 把x的各位右移y位
??? << ???? 左移 ?? x<<y ?? 把x的各位左移y位
??? >>> ??? 右移 ?? x>>>y ? 把x的各位右移y位,左邊填0
??? 舉例說明:
??? (1)有如下程序段:
??? int x = 64;?? //x等于二進制數的01000000
??? int y = 70;?? //y等于二進制數的01000110
??? int z = x&y?? //z等于二進制數的01000000
??? 即運算結果為z等于二進制數01000000。位或、位非、位異或的運算方法類同。
??? (2)右移是將一個二進制數按指定移動的位數向右移位,移掉的被丟棄,左邊移進的部分或者補0(當該數為正時),或者補1(當該數為負時)。這是因為整數在機器內部采用補碼表示法,正數的符號位為0,負數的符號位為1。例如,對于如下程序段:
??? int x = 70;?? //x等于二進制數的01000110
??? int y = 2;
??? int z = x>>y? //z等于二進制數的00010001
??? 即運算結果為z等于二進制數00010001,即z等于十進制數17。
??? 對于如下程序段:
??? int x = -70;? //x等于二進制數的11000110
??? int y = 2;
??? int z = x>>y? //z等于二進制數的11101110
??? 即運算結果為z等于二進制數11101110,即z等于十進制數-18。要透徹理解右移和左移操作,讀者需要掌握整數機器數的補碼表示法。
??? (3)0填充的右移(>>>)是不論被移動數是正數還是負數,左邊移進的部分一律補0。
?
5.其他運算符
???
(1)賦值運算符與其他運算符的簡捷使用方式
??? 賦值運算符可以與二元算術運算符、邏輯運算符和位運算符組合成簡捷運算符,從而可以簡化一些常用表達式的書寫。
??? 賦值運算符與其他運算符的簡捷使用方式
?? 運算符 用法 ? 等價于 ?? 說明
??? += ??? s+=i ?? s=s+i ??? s,i是數值型
??? -= ??? s-=i ?? s=s-i ??? s,i是數值型
??? *= ??? s*=i ?? s=s*i ??? s,i是數值型
??? /= ??? s/=i ?? s=s/i ??? s,i是數值型
??? %= ??? s%=i ?? s=s%i ??? s,i是數值型
??? &= ??? a&=b ?? a=a&b ??? a,b是邏輯型或整型
??? |= ??? a|=b ?? a=a|b ??? a,b是邏輯型或整型
??? ^= ??? A^=b ?? a=a^b ??? a,b是邏輯型或整型
??? <<= ?? s<<=i ? s=s<<i ?? s,i是整型
??? >>= ?? s>>=i ? s=s>>i ?? s,i是整型
??? >>>= ? s>>>=i s=s>>>i ? s,i是整型
???
(2)方括號[]和圓括號()運算符
???
方括號[]是數組運算符,方括號[]中的數值是數組的下標,整個表達式就代表數組中該下標所在位置的元素值。
??? 圓括號()運算符用于改變表達式中運算符的優先級。
?
???
(3)字符串加(+)運算符
??? 當操作數是字符串時,加(+)運算符用來合并兩個字符串;當加(+)運算符的一邊是字符串,另一邊是數值時,機器將自動將數值轉換為字符串,這種情況在輸出語句中很常見。如對于如下程序段:
??? int max = 100;
??? System.out.println("max = "+max);
??? 計算機屏幕的輸出結果為:max = 100,即此時是把變量max中的整數值100轉換成字符串100輸出的。
?
???
(4)條件運算符(?:)
??? 條件運算符(?:)的語法形式為:
??? <表達式1> ?<表達式2> : <表達式3>
??? 條件運算符的運算方法是:先計算<表達式1>的值,當<表達式1>的值為true時,則將<表達式2>的值作為整個表達式的值;當<表達式1>的值為false時,則將<表達式3>的值作為整個表達式的值。如:
??? int a=1,b=2,max;
??? max = a>b?a:b;?? //max等于2
?
???
(5)強制類型轉換符
???
強制類型轉換符能將一個表達式的類型強制轉換為某一指定數據類型,其語法形式為:
??? (<類型>)<表達式>
?
???
(6)對象運算符instanceof
???
對象運算符instanceof用來測試一個指定對象是否是指定類(或它的子類)的實例,若是則返回true,否則返回false。
?
???
(7)點運算符
??? 點運算符“.”的功能有兩個:一是引用類中成員,二是指示包的層次等級。
?
6.運算符的優先級
??? 以下按優先級從高到低的次序列出Java語言中的所有運算符,表中結合性一列中的“左?右”表示其運算次序為從左向右,“右?左”表示其運算次序為從右向左。
???
優先級 運算符 ??????????????????????????????????????? 結合性
??? 1 ????? .? []? ()? ;? ,
??? 2 ????? ++? ――? +=? !? ~? +(一元)?-(一元)??? ????????????? 右?左
??? 3 ????? *? /? % ???????????????????????????????????????????? 左?右
??? 4 ????? +(二元)? -(二元)????????????????????????????????????? 左?右
??? 5 ????? <<? >>? >>> ???????????????????????????????????????? 左?右
??? 6 ????? <? >? <=? >=? instanceof ??????????????????????????? 左?右
??? 7 ????? = =? != ???????????????????????????????????????????? 左?右
??? 8 ????? & ?????????????????????????????????????????????????? 左?右
??? 9 ????? ^ ?????????????????????????????????????????????????? 左?右
??? 10 ???? | ?????????????????????????????????????????????????? 左?右
??? 11 ???? && ????????????????????????????????????????????????? 左?右
??? 12 ???? || ????????????????????????????????????????????????? 左?右
??? 13 ???? ?: ???????????????????????????????????????????????? 右?左
??? 14 ???? =? *=? /=? %=? +=? -=? <<=? >>=? >>>=? &=? ^=? |= ? 右?左
?
7.表達式
??? 用運算符和圓括號把運算對象連接起來的、符合Java語言語法規則的式子稱作表達式。運算符是算術運算符的表達式稱作算術表達式,運算符是關系運算符的表達式稱作關系表達式,運算符是邏輯運算符的表達式稱作邏輯表達式,運算符是位運算符的表達式稱作位表達式。算術表達式中的運算對象必須是數值量,關系表達式中的運算對象必須是數值量,邏輯表達式中的運算對象必須是邏輯量,位表達式中的運算對象必須是整數數值量。
??? 運算符都有優先級,表達式按照運算符的優先級進行逐個計算,最后求得整個表達式的值。運算符中圓括號的優先級最高,圓括號還可以多層嵌套。在同一級括號內(或一個括號也沒有時),表達式按照運算符優先級高的先運算、同一運算符優先級的按照運算符的結合性(即從左向右還是從右向左)的次序進行運算。大多數運算符的結合性是從左向右,少數運算符的結合性(如賦值、條件運算等)是從右向左。
由于運算對象是有數據類型的,所以最終得到的計算結果也是有數據類型的,表達式結果的數據類型不一定和運算對象相同,它還取決于表達式的運算符。如:
??? int i=5;
??? (i<0)&(i>100)? ? //結果為boolean型
??? (i-2)*8+5? ?? ?? //結果為int型
??? "Abcde"+"12345"? //結果為String型
??? Java表達式既可以單獨組成語句,也可出現在循環語句、條件語句的條件部分,還可以出現在函數的實際參數調用等場合。
??? 實際上,從表達式的角度看,整個賦值語句是一個表達式,其運算方法是先計算出賦值運算符右邊的表達式的值(因賦值運算符的優先級最低),然后把該值賦給賦值運算符左邊的變量(因賦值運算符的結合性是先右后左)。
??? 最后,我們給出一個例子,用來說明上面討論過的Java語言基本要素。
?
【例2.2】求4x2 + 5x + 1 = 0方程的根。已知b2 – 4ac > 0。
public class Exam2_2
{
??? public static void main(String args[])
??? {
??????? double a = 4, b = 5, c = 1, disc, x1, x2, p, q;
??????? disc = b * b - 4 * a * c;
??????? p = - b / (2 * a);
??????? q = Math.sqrt(disc) / (2 * a);
??????? x1 = p + q;
??????? x2 = p - q;
??????? System.out.println("x1 = " + x1 + "????? x2 = " + x2);
??? }
}
其中,表達式Math.sqrt()為調用Math類的sqrt()方法,該表達式完成某個數的開平方。此例還說明,表達式還可以是某個類的方法調用(當然,數據類型要符合要求)。
程序運行結果為:
x1 = -0.25????? x2 = -1.0
?
6、流程控制語句
??? 流程控制語句用來控制程序的執行流程。流程控制語句有條件選擇語句、循環語句和轉移語句三種。
??? 任何程序的結構都是由三種基本的結構組成的。這三種基本結構是:順序結構、分支結構和循環結構。在Java程序中,通常一個以分號(;)結束的符號串稱為一條語句。在順序結構的程序或程序段中,程序是按語句次序、下一條語句接上一條語句順序被執行的。
??? 在分支結構或循環結構的程序或程序段中,程序不是按語句次序順序執行的,而是按分支結構語句或循環結構語句所規定的執行流程來執行的。為了滿足實際應用問題的設計需要,分支結構和循環結構有各種各樣的變形。另外,實際的程序設計中,經常需要轉移語句與分支語句或循環語句結合使用。
??? Java語言的流程控制語句有:
? 分支語句:if,switch
? 循環語句:for ,while,do-while
? 轉移語句:break,continue
??? 另外,函數或類的成員函數在運行結束后,需要返回原調用處,并可能需要帶回函數或成員函數的返回值,這種流程控制用return語句來實現。
?
1、分支語句
???
分支結構是指程序按照當前的分支條件控制程序流程的執行。
??? 有:if語句和switch語句
??? if語句實現二路分支,switch語句實現多路分支。
?
1.if語句
???
(1)基本的if 語句
??? if 語句的語法形式為:
??? if? (<邏輯表達式>)
??? <語句組1>;
??? [else <語句組2>;]
??? 其中,邏輯表達式的計算值是一個只可能是true或false的邏輯值。if語句的含義是:當<邏輯表達式>的值為true時,執行if 后面的<語句組1>;當<邏輯表達式>的值為false時,執行else后面的<語句組2>。當執行的語句組中的語句多于一條時,語句組必須用一對花括號“{}”括起來。在Java語言的語法中,一對方括號“[]”括起來的部分,表示該部分(除數組定義外)是任選的。因此,else語句是任選的,當沒有else語句時,若<邏輯表達式>的值為false時就執行if 語句后邊的語句。
?
【例2.3】找出a、b兩個數中的較大者并輸出。
方法一:用if-else結構實現。
public class Exam2_3
{
??? public static void main(String args[])
??? {
??????? int a = 5, b = 6, max;
??????? if( a > b )
??????? {
??????????? max = a;
??????????? System.out.println("max = " + max);
??????? }
??????? else
??????? {
??????????? max = b;
??????????? System.out.println("max = " + max);
??????? }
??? }
}
?
方法二:用沒有else的if結構實現。
public class Exam2_3_2
{
??? public static void main(String args[])
??? {
??????? int a = 5, b = 6, max;
??????? max = a;
??????? if( b > a )
??????????? max = b;
??????? System.out.println("max = " + max);
??? }
}
例2.3中if語句的邏輯表達式中只有一個條件。當問題復雜時,if語句的邏輯表達式中的條件可能多于一個,這稱為復合條件。
復合條件需要用邏輯運算符——邏輯與(&&)、邏輯或(||)、邏輯非(!)、邏輯異或(^)等邏輯運算符來組合條件。
例如下面的if語句條件為,判斷n是否為一個1至100區間的數:
if (n >= 1 && n <= 100)
如果n既大于等于1又小于等于100,則條件為true,否則條件為false。
?
(2)if語句嵌套
???
如果if語句中又包括另一個if語句,則稱為if語句嵌套。
??? if (n >= 1)
??? {
????? if (n <= 100) ……
??? }
??? else ……
??? 在兩個嵌套的if語句中,如果有一個if語句省略了else語句,會產生二義性。如:
??? if (n >= 1)
??? if (n <= 100) ……
??? else ……
??? 此時,else是和哪個if語句匹配容易產生混淆。Java語言規定:else總是與最近的一個if語句匹配。
??? 所以此處else應理解為是與第二個if語句匹配(注意:書寫的縮進格式與匹配無關)。如果要求else是與第一個if語句匹配,則程序應寫為:
??? 一個if語句可以有兩個分支,利用if語句嵌套可以組合出多于兩個的分支。
【例2.4】找出三個整數中的最大數并輸出。
方法一:用if語句嵌套方法。
public class Exam2_4
{
??? public static void main(String args[])
??? {
??????? int a = 3, b = 1, c = 2, max;
?
??????? if(a < b)
??????????? if (b < c)
??????????????? max = c;
??????????? else
??????????????? max = b;
??????? else
??????????? if (a < c)
??????????????? max = c;
??????????? else
??????????????? max = a;
??????? System.out.println("max = " + max);
??? }
}
程序運行結果:
max = 3
方法二:用條件的邏輯組合方法。
public class Exam2_4_2
{
??? public static void main(String args[])
??? {
??????? int a = 3, b = 1, c = 2, max;
?
??????? if(a < b && b < c)
??????????? max = c;
??????? else if(a < b && c < b)
??????????? max = b;
??????? else if (a > b && a < c)
??????????? max = c;
??????? else?????????????????????? //即(a > b && a > c)
??????????? max = a;
??????? System.out.println("max = " + max);
??? }
}
說明:條件兩兩組合,所以條件的邏輯組合共有四種情況。此問題可不考慮兩個數相等的情況。
?
2.switch語句
??? switch語句是多個分支的流程控制語句
??? 語法形式為:
??? switch (<表達式>)
??? {
??? case<常量1>:<語句組1>;
??? ??? [break;]
??? case<常量2>:<語句組2>;
??? ??? [break;]
??? ……;
??? [default;<語句組>]
??? }
??? 其中switch、case 、default是關鍵字,default語句是任選的。
??? switch語句的語義是:將<表達式>的值按照從上至下的順序與case語句中給出的常量值進行比較,當表達式的值與某個case語句中的常量值相等時,就執行相應case后的語句序列;若沒有一個常量值與表達式的值相等,則執行default語句。如果沒有default語句,并且表達式與所有case的常量都不相等時,則不做任何操作。
??? switch表達式和case常量值的類型可以是byte、short、int、long和char,但不能為boolean,并且要求兩者的數據類型必須一致。
?
3.switch語句中的break語句
???
switch語句本身并不能保證執行完一組case后的語句或語句組后,跳過隨后的case判斷,通常情況下,此時需要用break語句來跳過隨后的case語句。
??? break語句的語法形式是:
??? break;
??? switch語句中的break語句的語義是:跳過break語句所在位置隨后所有的case語句,即結束switch語句的執行。
【例2.5】?? 把數值表示的星期轉換成相應的英文表示并顯示。
public class Exam2_5
{
??? public static void main(String args[])
??? {
??????? int week = 5;
??????? System.out.print("week = " + week + "?? ");
??????? switch (week)
??????? {
??????????? case 0: System.out.println("Sunday");?? break;
??????????? case 1: System.out.println("Monday");?? break;
??????????? case 2: System.out.println("Tuesday");? break;
??????????? case 3: System.out.println("Wednesday");break;
??????????? case 4: System.out.println("Thursday"); break;
??????????? case 5: System.out.println("Friday");?? break;
??????????? case 6: System.out.println("Saturday"); break;
??????????? default: System.out.println("Data Error!");
??????? }
??? }
}
程序運行結果:
week = 5?? Friday
?
2、循環語句
??? 循環結構是指程序按照當前的循環條件控制程序流程的執行。Java語言有三種循環結構的語句:for語句、while語句和do-while語句。這三種循環語句雖然控制循環的方式不同,但實現循環的功能相同。換句話說,對于任何一個循環問題,這三種循環語句都可以實現。但是,不同的循環問題,使用這三種循環語句的簡便程度不同。因此,一個好的程序設計者,應該學會針對不同的循環問題,選擇最簡便的循環語句。
?
1.for語句
???
for語句的語法形式為:
??? for ([<表達式1>];[<表達式2>];[<表達式3>])
??? <循環體>;
???
for語句的語義是:首先計算<表達式1>的值,然后計算<表達式2>的值,如果<表達式2>值為true時,執行一次<循環體>,再計算<表達式3>的值,并進行下一次循環過程;當<表達式2>的值為false時,循環過程結束。
??? 在for語句中,<表達式1>是給循環變量賦初值,因此,<表達式1>通常是一個賦值表達式;<表達式2>是給出循環結束條件,因此,<表達式2>必須是一個關系表達式或邏輯表達式;<表達式3>是改變循環變量,因此,<表達式3>必須是一個賦值表達式(或類似i++形式的改變變量i的數值的語句);<循環體>可以是一條語句,也可以是多條語句,當為多條語句時,必須用一對花括號“{}”括起來。
??? 說明:無論是<表達式1>還是<表達式2>或者是<表達式3>,都可以任選。
?
【例2.6】?? 求1到10的累加和。
for語句最適合于循環次數已知的循環結構。此問題的循環次數已知,因此,此問題適合于用for語句實現。
public class Exam2_6
{
??? public static void main(String args[])
??? {
??????? int i, n = 10, sum = 0;
???????
??????? for(i = 1; i <= n; i++)
??????????? sum = sum + i;
??????? System.out.println("Sum = " + sum);
??? }
}
程序運行結果為:
Sum = 55
上述for語句循環過程也可以設計成遞減形式的,此時的for語句為:
for(i = n; i >= 1; i--)
sum = sum + i;
2.while語句
???
while語句的語法形式為:
?? while (<邏輯表達式>)
??? <循環體>;
???
while語句的語義是:如果<邏輯表達式>的計算結果為true時,則執行循環體;如果<邏輯表達式>的計算結果為false時,則結束while語句的執行。同樣,當<循環體>中的語句多于一條時,需要用一對花括號“{}”括起來。
??? 例如用while語句實現求1到10累加和的程序段如下:
??? int i = 1,n = 10,sum = 0;
??? while (i <= n)
??? {
??? ??? sum = sum + i;
??? ??? i++;
??? }
??? 和for語句相比,while語句循環中的循環變量賦初值(i = 1)、循環過程結束判斷(i <= n)和循環變量修改(i++)三個部分都有,只是放在了不同的地方。
??? 在while語句的循環結構中,初學者最容易犯的一個錯誤是,忘記在循環體中修改循環變量的值,此時循環過程將永不結束,俗稱為“死循環”。如上面的程序段中如果沒有i++語句,則循環過程將永不結束。
??? 死循環的另一種情況是,循環結束條件永遠無法滿足。例如:
??? int i = 1,n = 10,sum = 0;
??? while (i >= 0)
??? {
???? ?? sum = sum + i;
???? ?? i++;
??? }
??? 上述程序段的循環體中雖然有i++語句改變循環變量i的值,但i值的變化永遠都滿足i >= 0,即循環結束條件永遠不會滿足,因此造成死循環。
??? while語句適合于循環次數不確定的情況。如上所示,雖然while語句也可以用來構造循環次數已知的循環過程,但是,很顯然,此種情況用for語句構造循環過程更簡單、更明了一些。
?
【例2.7】求兩個不為0的正整數的最大公約數。
對于求兩個不為0的正整數的最大公約數問題,歐幾里德提出了輾轉相除算法,其算法思想是:
(1)令m為兩個整數中的較大者,n為兩個整數中的較小者;
(2)用m除以n,令r為m除以n的余數;
(3)若r不等于0,則令m等于n,n等于r,返回步驟(2)繼續;若r等于0,則n中的數值就是兩個整數的最大公約數。
從上述算法思想可知,該算法是一個循環過程,并且該循環過程的循環次數事先無法知道,因此,該問題適合于用while語句構造循環過程。
public class Exam2_7
{
public static void main(String args[])
{
int m = 48, n = 32, r = 0, temp;
???????
???????? if(m <= 0 || n <= 0)
???????? {
?????????? System.out.println("數據錯誤!");
???????????? return;
???????? }
???????
???????? if(m < n)?????????????????????? //保證m >= n
{
?????? temp = m;
?????? m = n;
?????? n = temp;
? }
?
? r = m % n;?????????????????????? //循環初始化
? while(r != 0)?????????????? //循環條件判斷
? {
?????? m = n;
?????? n = r;
?????? r = m % n;???????????? //循環變量修改
? }
?
???????? System.out.print("最大公約數 = " + n);
???? }
}
程序運行結果:
最大公約數 = 16
當然,上面程序中的循環過程也可以用for語句構造,用for語句構造循環過程相應的程序段如下:
for(r = m % n; r != 0; r = m % n)???? //for循環???
{
??? m = n;
??? n = r;???
}
for語句的循環過程中,也必須有循環初始化(r = m % n)、循環條件判斷(r != 0)和循環變量修改(r = m % n),只是處于不同的位置而已。顯然,在循環次數不知時,用for語句構造的循環過程不及用while語句構造的循環過程清晰。
?
3.do-while語句
???
do-while語句的語法形式為:
??? do
??? {
??? ??? <語句組>;
??? }? while (<邏輯表達式>) ;
???
do-while語句的語義是:首先執行語句組(或稱循環體),然后計算<邏輯表達式>的值,當<邏輯表達式>的值為true時,執行一次循環體;當<邏輯表達式>的值為false時,結束循環。
??? 從語義看,do-while語句和while語句的惟一差別是:do-while語句至少執行一次循環體(因其結束條件判斷在后面進行);而對于while語句來說,當一開始循環條件就不滿足時,循環體將一次也不執行。
??? 例2.7求最大公約數程序的循環部分也可以用do-while語句構造。用do-while語句的相應程序段如下:
??? r = m % n;????????????? //循環初始化
??? if(r != 0)????????????? //判斷初始時r是否為0
??? ??? do??
??? ??? {
??? ??????? m = n;
??? ??????? n = r;
??? ??????? r = m % n;????? //循環變量修改???????
??? } while(r != 0);????? ? //循環結束條件判斷
??? 由于語句r = m % n的計算結果可能使r等于0,而do語句在第一次執行循環體時,并不做任何判斷,這將可能造成因r等于0使n等于0,因n等于0使語句r = m % n的運算出現除數等于0的錯誤,因此要在do語句之前判斷r是否等于0。只有在r不等于0時才執行do語句;在r等于0時最大公約數已經得到。
顯然,對于求最大公約數問題,用while語句比用do-while語句簡單一些。但在有些情況下,用do-while語句構造循環過程比用while語句簡單一些。
4.多重循環
??? 如果循環語句的循環體內又有循環語句,則構成多重循環結構。多重循環結構中的循環語句,可以是前面討論過的for語句、while語句或do-while語句中的任何一種。
【例2.8】輸出九九乘法表。
程序如下:
public class Exam2_8
{
??? public static void main(String args[])
??? {
??????? int i,j,n = 9;
??????? for(i = 1; i <= n; i++)???????????????? //外層循環
??????? {
??????????? for(j = 1; j <= i; j++)???????????? //內層循環
??????????????? System.out.print("? " + i*j);?? //輸出
??????????? System.out.println();?????????????? //每行結束時換行
??????? }
??? }
}
說明:這個問題中,兩重循環的循環次數都已知,因此兩重循環都用for語句構造循環過程。外層for語句的循環變量是i,控制總共打印多少行,內層for語句的循環變量是j,控制每行顯示多少列。
程序運行結果為:
1
2? 4
3? 6? 9
4? 8? 12? 16
5? 10? 15? 20? 25
6? 12? 18? 24? 30? 36
7? 14? 21? 28? 35? 42? 49
8? 16? 24? 32? 40? 48? 56? 64
9? 18? 27? 36? 45? 54? 63? 72? 81
當應用問題復雜時,程序一般需要有多重循環結構,此時最重要的是要把程序設計的思路梳理清楚,而其中的每一重循環結構都可以按單重循環結構設計。
?
3、break語句和continue語句
??? break語句通常是和switch語句或循環語句配合使用,continue語句通常是和循環語句配合使用。
?
1.break語句
???
break語句的語法形式是:
??? break;
??? 在上節討論switch語句時,我們已結合介紹了switch語句中的break語句使用方法。這里我們主要介紹循環語句中的break語句使用方法。在循環語句中,break語句的功能是跳出循環體。特別需要說明的是,當break語句位于多重循環語句的內層時, break語句只能跳出它當前所處的那層循環體。
【例2.9】循環語句中break語句使用方法示例。
public class Exam2_9
{
??? public static void main(String args[])
??? {
???????? int i, j, k;
????????
???????? for(i = 1; i <= 6; i++)???? //第1層循環
???????? {
???????????? for(j = 1; j <= 6; j++)??? //第2層循環
???????????? {
??????????????? for(k = 1; k <= 6; k++)?? //第3層循環
??????????????? {
??????????????????? System.out.println("k = " + k + "???? ");
??????????????????? if(k == 2) break;?????????????? //跳出第3層循環
??????????????? }
??????????????? System.out.println("j = " + j + "???? ");
??????????????? if(j == 2) break;?????????????????? //跳出第2層循環
???????????? }
??????????? System.out.println("i = " + i + "???? ");
??????????? if(i == 2) break;??????????????????????? //跳出第1層循環
???????? }
??? }
}
由于break語句的作用,此程序的第3層的輸出語句(輸出k)只執行了8次,第2層的輸出語句(輸出j)只執行了4次,第1層的輸出語句(輸出i)只執行了2次。
2.continue語句
???
continue語句的語法形式為:
????
continue;
??? continue語句主要用于循環語句中,continue語句的語義是:若循環體中遇到continue語句,則本次循環體的后續語句被忽略,回到循環條件判斷處,判斷是否執行下一次循環體。換句話說,continue語句僅跳過當前層循環體的剩余語句。
【例2.10】continue語句使用方法示例。
public class Exam2_10
{
??? public static void main(String args[])
??? {
???????? int i, j;
????????
???????? for(i = 1; i <= 6; i++)
???????? {
???????????? for(j = 1; j <= 6; j++)
???????????? {
???????????????? if(j >= 3) continue;??? //continue語句
???????????????? System.out.println("j = " + j + "???? ");
???????????? }
???????? }
??? }
}
由于continue語句的作用,第2層的輸出語句只執行了12次。
?
4、return語句
?
??? return語句的語法形式為:
??? return? [<返回值>];
??? return語句的語義是:使函數返回原調用處,且帶回返回值。如果函數為void類型,則return語句后沒有<返回值>;如果函數為非void類型,則return語句后需要有<返回值>,并且<返回值>的類型必須和函數的類型一致。
??? 當return語句不帶<返回值>,并且位于函數的最后時,return語句可以省略。
??? return語句的具體使用方法可參見隨后各章的程序設計舉例。
?
?
7、程序注釋
??? Java語言允許在程序中添加注釋,以增加程序的可讀性。前面的例子中已經多次使用了程序注釋。注釋主要是給人閱讀的,所以系統不會對注釋的內容進行編譯。
??? Java語言有三種形式的注釋:
??? 單行注釋?????? // 注釋內容
??? 多行注釋?????? /* ……
?????????????????? 多行注釋內容
?????????????????? ……*/
??? 文件注釋?????? /**……
?????????????????? 文件注釋內容
?????????????????? */
?
8、數組
??? 數組是連續內存單元中一組名字和數據類型相同的數據元素的有限集合。數組可以用來保存和處理一組數據類型相同的數據元素。數組中的每個數據元素稱作一個數組元素。
當把一維數組中的每個數據元素定義為一個一維數組時,就構成了Java語言的二維數組,以此類推,還可以有三維數組甚至更多維數組。另外,Java語言可以構造出不規則數組。
?
1、一維數組
???
和變量的使用方法類同,一維數組也要先定義后使用,不同的是數組在定義后還要經過內存單元分配后才能使用。
??? Java語言一維數組的使用分三步:定義一維數組變量、為數組分配內存單元和使用數組元素。
?
1.一維數組變量定義
???
一維數組變量定義的語法形式為:
???
<數據類型><數組名>[];
??? 或
??? <數據類型>[]<數組名>;
???
其中,方括號[]表示定義的是數組變量,<數據類型>定義了數組元素的數據類型,<數組名>定義了數組名的標識符。
??? 也可以把數組類型看成是Java語言在基本數據類型的基礎上的擴展。
??? 例如:
???
int[]? a;
??? 定義了一個數據類型為int、數組標識符為a的一維數組。
在數組定義后,系統將給數組標識符分配一個內存單元,用于指示數組在內存中的實際存放位置。由于在數組變量定義時,數組元素本身在內存中的實際存放位置還沒有給出,所以,此時該數組名的值為空(null)。例如,上述語句執行后數組a的狀態如圖下圖中的(a)所示:
??
????
?
2.為數組分配內存單元
???
Java語言中,new是一個特殊的運算符。new運算符的語法形式為:
??? new <數據類型>
??? new運算符的語義是:向系統申請指定數據類型所需的內存單元空間。new運算符返回所申請內存單元的首地址。
??? 數組元素本身的內存空間必須用new運算符在程序中申請。只有用new運算符為數組分配了內存單元空間后,存放一個數組的所有數組元素所需的內存空間才真正被系統分配了。為數組類型變量分配內存單元的語法形式為:
??? <數組名> =? new <數據類型>[<長度>];
???
其中,<數組名>必須是已定義的數組類型變量,<數據類型>必須和定義數組名時的數據類型一致,方括號[]內的<長度>指出了當前數組元素的個數。
??? 例如:
??? a = new int[5];
??? 就具體分配了包含5個int類型數組元素的內存單元,并把該塊內存單元的首地址賦值給數組名a
??? Java語言規定,在數組分配內存單元后,系統將自動給每個數組元素賦初值,并規定:數值類型的數組元素初值為0,邏輯類型的數組元素初值為false,類類型的數組元素初值為null。執行該語句后的示意圖如上圖中的(b)
?
3.使用數組元素
??? 一旦完成了定義數組變量和為數組分配內存單元后,就可以使用數組中的任意數組元素。數組元素由數組名、一對方括號、方括號中的整數數值(一般稱作下標)組成。其中下標指出了希望操作的數組元素位置。下標由0開始,其最大值為用new運算符分配內存單元時規定的長度值減1。各數組元素在內存中按下標的升序連續存放。上述數組a的5個元素依次是a[0],a[1],a[2],a[3],a[4]。
??? 例如:
??? a[0] = 10;
??? 語句就給數組元素a[0]賦了數值10。執行該語句后的示意圖如上圖中的(c)
4.引用類型
??? 前面討論的用基本數據類型定義變量和這里討論的定義數組變量有一些不同。用基本數據類型定義的變量,其變量名表示這個變量名中存放的數值,如有下列語句段:
??? int i, x;?? ? //定義變量
??? i = 10;??? ?? //給變量i賦值
??? x = 10 + i;?? //使用變量i中的數值
??? 上述語句段中,變量i的存儲結構如下圖中的(a)所示,語句 x = 10 + i中,賦值號右邊的變量i表示變量i中的數值10。
???
???
??? 對于數組變量,設有下列語句段:
??? int[]? a;
??? int x;
??? a = new int[5];
??? a[0] = 10;??? ? //給數組元素a[0]賦值
??? x = 10 + a[0];? //使用數組元素a[0]中的數值
??? x = 10 + a;?? ? //錯誤,數值10和數組名 a為不兼容的類型
??? 上述語句段中,數組a的存儲結構如上圖中的(b)所示,語句 x = 10 + a[0]中,賦值號右邊的數組元素a[0]表示數組元素a[0]中的數值,但語句x = 10 + a將出錯,因為數組名 a是指向內存中存放數組元素的一片連續內存單元的首地址,所以,數值10和數組名 a為不兼容的類型。
??? Java語言中,數組名的類型是引用類型。所謂引用類型,是指該類型的標識符表示的是一片內存連續地址的首地址。
??? 引用類型是非常重要的一個概念。下一節要討論字符串,字符串名和數組名一樣,也是引用類型。
?
5.數組的簡化使用方法
??? 數組的定義和為數組分配內存空間兩步可以結合起來。
??? 例如:
??? int a[] = new int[ 5];
??? 就在定義int類型數組變量a的同時為數組分配了5個int類型數組元素所需的內存空間,并給每個數組元素初始賦值0。
??? 數組元素的初始化賦值也可以和上述語句結合在一起完成,此時采用簡寫形式。例如,
??? int a[] = {1,2,3,4,5};
??? 就在定義int類型數組變量a、為數組分配了5個int類型數組元素所需的內存空間的同時,初始化給數組元素a[0]賦初值1,a[1]賦初值2,……,a[4]賦初值5
?
6.數組元素允許的運算
???
對數組元素可以進行其數據類型所允許的任意運算。
??? 例如:
??? int u = 3, v = 4, x, y;
??? int a[] = {1,2,3,4,5};
??? x = (a[2] + a[3] – u) * v;
??? y = a[1] / u;
??? 都是合法的表達式。
?
7.數組的長度
??? Java語言提供了length成員變量返回數組元素的個數,其使用方法為:
??? <數組名>.length
??? 例如:
??? int n;
??? int a[] = new int[ 10];
??? n = a.length;
??? 則有n等于10。
?
8.數組長度的重新定義
??? 一旦為數組規定了長度,在程序中使用數組時就不能超過所規定的長度,否則編譯時會給出“數組下標越界”的語法錯誤。例如,若數組分配的內存空間為5個,則語句中一旦出現a[5]將產生“數組下標越界”的語法錯誤。
??? 上述情況下,可以用new運算符重新為數組分配內存單元。例如,
??? a = new int[ 10];
??? 上述語句后,由于重新為數組a分配了10個int類型的內存單元空間,所以,此時若語句中出現a[5],編譯時將不會出現“數組下標越界”的語法錯誤。
【例2.11】求10個數中的最小數。
要求:用數組初始化賦值方法給出10個整數數值。
程序設計如下:
public class Exam2_11
{
??? public static void main(String args[])
??? {
???????? int i, min;
???????? int a[] = {30,81,37,45,26,46,44,78,80,64}; //初始化賦值
????????
???????? System.out.print("數組元素為:");???????????
???????? for(i = 0; i < a.length; i++)
???????????? System.out.print("? " + a[i]);??? //輸出數組元素
?
???????? //尋找數組中數值最小的元素
???????? min = a[0];
???????? for(i = 1; i < a.length; i++)
???????????? if(a[i] < min)? min = a[i];
?
???????? System.out.println("\n最小數為:" + min);
???? }
}
程序的運行結果為:
數組元素為:? 30? 81? 37? 45? 26? 46? 44? 78? 80? 64
最小數為:26
如果此問題不用數組方法設計,而用簡單變量方法設計,程序將非常復雜。因此,數組是復雜問題的程序設計所必需的。
------------------------------------------------------------------------------------------------------
【例2.12】把10個數按從小到大的次序排序。
要求:用數組初始化賦值方法給出10個整數數值,用直接交換排序算法排序。
直接交換排序算法思想:例2.11程序找到的是數組a中的最小數。如果我們在此基礎上設計一個循環過程,把每次找到的最小數和數組中尚未排好序的數據元素交換,下次循環時,從這個數據元素的下一個位置開始,繼續這樣的尋找和交換過程。這樣的過程共進行a.length-1次,則全部數組中的數據元素就按從小到大的次序排好了。
程序設計如下:
public class Exam2_12
{
??? public static void main(String args[])
??? {
??????? int a[] = {30,81,37,45,26,46,44,78,80,64};
??????? int i, j, min, temp;
??????
??????? System.out.println("排序前數組元素為:");
??????? for(i = 0; i < a.length; i++)
??????????? System.out.print(a[i] + "? ");
?
? //直接交換排序
? for(i = 0; i < a.length-1; i++)???????? //循環a.length-1次
? {
??????????? min = i;????
??????????? for(j = i+1; j < a.length; j++)
??????????????? if(a[j] < a[min]) min = j;??????? //尋找最小數
?
??????????? if(min != i)???????????????????????????? //判斷是否需要交換
??????????? {
??????????????? temp = a[i];
??????????????? a[i] = a[min];
??????????????? a[min] = temp;
??????????? }
}
?
??????? System.out.println("\n排序后數組元素為:");
??????? for(i = 0; i < a.length; i++)
??????????? System.out.print(a[i] + "? ");
??? }
}
程序的運行結果為:
排序前數組元素為:
30? 81? 37? 45? 26? 46? 44? 78? 80? 64
排序后數組元素為:
26? 30? 37? 44? 45? 46? 64? 78? 80? 81
?
2、二維數組
?
???
Java語言只定義了一維數組,但是,如果一維數組的每個數組元素都是一個一維數組,則構成了Java語言的二維數組。和一維數組的使用方法類同,二維數組的使用也分三步:定義數組變量、為數組分配內存單元和使用數組元素。
?
1.二維數組定義:
??? 二維數組變量定義的一個例子如下:
??? int a[][];
??? 或
??? int[] a[];
???
上面語句定義了一個數據類型為int[](即一維數組類型)、標識符為a的一維數組,即數組a是二維數組。
??? 上述語句執行后數組a的內存狀態如下圖中的(a)所示:
?
???
??? 為二維數組變量分配內存單元時必須指定每一維的數組元素個數。
??? 例如:
??? a = new int[3][3];
??? 就具體分配了包含3個int[3]類型數組元素的內存單元,并把該連續內存單元的首地址賦給數組名a,同時為每個數組元素初始化賦值0。
??? 上圖中的(b)就是上述語句執行后的內存示意圖。
??? 使用二維數組元素的方法和使用一維數組元素的方法類同,只是這里要指出二維數組的每一維的下標。例如,語句
??? a[0][0] = 10;
??? 就給數組元素a[0][0]賦了數值10。如上圖(c)所示。
2.二維數組簡化:
??? 同樣,二維數組也可以用簡化方法。例如:
???
int a[][] = new int[5][5];
??? 就在定義int類型的二維數組變量a的同時,為數組分配了內存單元結構如圖2.2(b)所示的5個每一維為int[5]類型數組元素的內存空間,并給每個數組元素初始賦值0。
??? 又例如:
??? int a[][] = {{1,2,3},{4,5,6},{7,8,9}};
??? 就在定義int類型二維數組變量a、并為二維數組動態分配了9個int類型數組元素內存空間的同時,初始化給數組元素a[0][0]賦初值1,a[0][1]賦初值2,a[0][2]賦初值3,a[1][0]賦初值4,……,a[2][2]賦初值9。
??? 三維數組或更多維數組的使用方法和二維數組的使用方法類同。
【例2.13】求C = A×BT,其中,A是一個行向量,BT是一個列向量,C是一個矩陣。例如,設A和B均為n=3的向量,則矩陣C元素的計算方法是:c11=a1*b1,c12=a1*b2,c13=a1*b3,c21=a2*b1,……,c33=a3*b3。
設計思想:這是一個矩陣運算。用一維數組 a存放行向量A,用一維數組 b存放列向量BT,用兩維數組存放矩陣C。
程序設計如下:
public class Exam2_13??
{
??? public static void main(String args[])
??? {
??????? final int n = 3;
??????? int a[] = {1,2,3};
??????? int b[] = {4,5,6};
??????? int c[][] = new int[n][n];
??????? int i, j;
?
??????? for(i = 0; i < n; i++)
??????????? for(j = 0; j < n; j++)
??????????????? c[i][j] = a[i] * b[j];????? //計算cij
?
??????? System.out.println (”二維數組元素為:”);
??????? for(i = 0; i < n; i++)????????????
??????? {
??????????? for(j = 0; j < n; j++)
??????????????? System.out.print(c[i][j] + "?? ");
??????????? System.out.println();
??????? }
??? }
}
程序運行輸出結果為:
二維數組元素為:
4?? 5?? 6
8?? 10?? 12
12?? 15?? 18
?
3、不規則的二維數組
?
???
由于Java語言的二維數組是由一維數組定義的,所以,可以把二維數組中的每個一維數組定義為不同的元素個數,這樣就可以構成不規則的二維數組。
??? 不規則二維數組的具體設計方法是:先定義一個二維數組變量,并指定第一維的元素個數,然后再分別為第二維數組(即第一維數組的每個數組元素)分配不同的內存單元。由于此時是分別為第二維數組分配內存單元,并且第二維數組所分配的內存單元個數可以是不相同的,因此就構成了不規則的二維數組。
??? 例如,下面的代碼先定義一個二維數組,并為數組的第一維數組元素分配空間(這就要求必須指定其具體個數),然后再分別為第二維數組元素分配不同的內存空間。
??? int twoDim [][] = new int [4][]; //定義二維數組,并指定第一維的元素個數
??? twoDim[0] = new int[1];?? //指定第二維第一個元素的個數
??? twoDim[1] = new int[2];?? //指定第二維第二個元素的個數
??? twoDim[2] = new int[3];?? //指定第二維第三個元素的個數
??? twoDim[3] = new int[4];?? //指定第二維第四個元素的個數
??? 數組twoDim得到的內存單元結構如下圖所示:
?
???
?
【例2.14】計算并保存九九乘法表,要求重復的部分只保存一個。
設計思想:九九乘法表需要一個二維數組來保存,因為要求重復的部分(如1*2和2*1)只保存一個,所以需要把二維數組定義成不規則的二維數組。
程序設計如下:
public class Exam2_14
{
??? public static void main(String args[])
??? {
???????? final int N = 9;
???????? int a[][] = new int [N][];? //定義二維數組,并指定第一維的元素個數???????
???????? int i,j;
?
???????? for(i = 0; i < N; i++)
???????????? a[i] = new int [i+1];???????????? //指定不規則的第二維的個數
?
???????? for(i = 0; i < N; i++)?????
???????????? for(j = 0; j <= i; j++)???????
???????????????? a[i][j] = (i + 1) * (j + 1);??? //保存乘法表
??????
//輸出乘法表
???????? for(i = 0; i < N; i++)????????????????
???????? {
?????????? for(j = 0; j <= i; j++)
?????????????? System.out.print(a[i][j] + "?? ");
???????????? System.out.println();
???????? }
???? }
}
程序運行輸出如下:
1
2?? 4
3?? 6?? 9
4?? 8?? 12?? 16
5?? 10?? 15?? 20?? 25
6?? 12?? 18?? 24?? 30?? 36
7?? 14?? 21?? 28?? 35?? 42?? 49
8?? 16?? 24?? 32?? 40?? 48?? 56?? 64
9?? 18?? 27?? 36?? 45?? 54?? 63?? 72?? 81
?
?
9、字符串
??? 字符串是由n(n≥0)個字符組成的序列。為了把一個字符串和別的語言成分區分開來,Java中的字符串用一對雙引號括起來,一個字符串中的字符個數稱作字符串的長度。如"abc"就是一個長度為3、其值為abc的字符串。
??? Java中的字符串變量用String來定義,但和char、int等基本數據類型不同的是,String不是一個數據類型,而是一個類。String是Java應用程序接口(即Java API)中定義的一個類。由于應用程序一般要有輸出,常用的系統標準輸出要求輸出參數是一個字符串,因此,本節簡單介紹字符串的概念和使用方法。
1.字符串常量
??? 一對雙引號括起來的任何字符序列都是一個字符串常量,如""和"sum" 都是字符串常量。字符串常量""的長度為0,字符串常量"sum"的長度為3。
2.字符串變量
??? 定義字符串變量的方法和定義基本數據類型變量的方法類同。如下面語句就定義了兩個字符串變量str1和str2:
??? String str1, str2;
??? 在定義字符串變量時可以同時賦值,例如,下面語句就在定義字符串變量str的同時,給str賦了初值"abc":
??? String str = "abc";
??? 還可以定義String數組,例如,語句:
??? String[] v = new String[3];
??? 就定義了一個有3個數組元素的String數組v
?
3.字符串變量名
??? 和數組名一樣,字符串變量名也是引用類型,即字符串變量名是指向內存中一片連續內存單元的首地址。
?
4.字符串的賦值
??? 字符串變量定義后可以給該變量賦值。例如:
??? String str;
??? str = "abc";
??? 上述字符串變量定義和變量賦值也可以寫在一個語句中:
??? String str = "abc";
??? 上述語句的功能是:首先,定義字符串變量str;然后,向系統申請字符類型的長度為3的一片連續內存單元,并把字符’a’、’b’、’c’依次存入內存單元中;最后,把這片連續內存單元的首地址賦給字符串變量名str,即讓str指向存放字符串"abc"的內存單元的首地址。
??? 給字符串變量賦值時,還可以賦多個,其方法等同于數組聲明時賦值。例如:
??? String[] v={"Hello world!","Hello China!","Hello XSYU!"};
??? 該語句就給字符串變量v 賦了3個字符串常量值。
?
5.字符串的連接運算
??? Java語言提供了特殊的字符串運算符“+”,運算符“+”表示把兩個字符串連接起來。例如:
??? String str = "abc" + "def";
??? 該語句就把字符串值"abcdef",賦給了字符串變量str。
?
6.標準輸出中的字符串
??? 前面已經多次使用了系統的標準輸出System.out.print()和System.out.println()。這兩個輸出語句要求的參數是字符串或字符串表達式。例如,
??? String str = "abc";
??? System.out.print("def");
??? System.out.print(str);
??? System.out.print(str + "def");
??? 都是合法的輸出語句。
??? 前面有如下形式的輸出語句:
??? int j = 10;
??? System.out.print("j = " + j);
??? 其中,"j = "是一個字符串,j是一個int類型的變量,其數值為10,顯然,表達式"j = " + j的數據類型不一致,在這里,系統將把int類型的數值10轉換為字符串類型。
??? 因此上面語句將輸出:
??? j = 10
?
?
?
?
?
?