3.1Java編程概況
現(xiàn)在你可以復(fù)習(xí)一下Java語(yǔ)言的背景材料,它的基本結(jié)構(gòu)象C/C++,但任何用面向過(guò)程語(yǔ)言編寫過(guò)程序的人都可以了解Java語(yǔ)言的大部分結(jié)構(gòu).
3.1.1程序結(jié)構(gòu)
Java語(yǔ)言的源程序代碼由一個(gè)或多個(gè)編譯單元(compilationunit)組成,每個(gè)編譯單元只能包含下列內(nèi)容(空格和注釋除外):*一個(gè)程序包語(yǔ)句(packagestatement)*入口語(yǔ)句(importstatements)*類的聲明(classdeclarations)*界面聲明(interfacedeclarations)每個(gè)Java的編譯單元可包含多個(gè)類或界面,但是每個(gè)編譯單元最多只能有一個(gè)類或者界面是公共的。Java的源程序代碼被編譯?reg;后,便產(chǎn)生了Java字節(jié)代碼。Java的字節(jié)代碼由一?copy;不依賴于機(jī)器的指令組成,這?copy;指令能被Java的運(yùn)行系統(tǒng)(runtimesystem)有效地解釋。Java的運(yùn)行系統(tǒng)工作起來(lái)如同一臺(tái)虛擬機(jī)。在當(dāng)前的Java實(shí)現(xiàn)中,每個(gè)編譯單元就是一個(gè)以.java為后綴的文件。每個(gè)編譯單元有若干個(gè)類,編譯后,每個(gè)類生成一個(gè).class文件。.class文件是Java虛擬機(jī)能夠識(shí)別的代碼。
3.1.2注釋
三種類型如下://注釋一行/*一行或多行注釋*//**文檔注釋**/文檔注釋一般放在一個(gè)變量或函數(shù)定義?reg;前,指示在任何自動(dòng)生成文檔系統(tǒng)中調(diào)入。這?copy;注釋都是聲明條目的描述.。
3.1.3標(biāo)識(shí)符
變量,函數(shù),類和對(duì)象的名稱都是標(biāo)識(shí)符,程序員需要標(biāo)識(shí)和使用的東西都需要標(biāo)識(shí)符。在Java語(yǔ)言里,標(biāo)識(shí)符以字符或_,$開頭,后面可以包含數(shù)字,標(biāo)識(shí)符是大小寫有區(qū)別的,沒(méi)有長(zhǎng)度限制。
有效的標(biāo)識(shí)符mynameict_networkHello_sys_path$bill
例子:inta_number;char_onechar;float$bill;
3.1.4數(shù)據(jù)類型
Java使用五種基本類型:integer(整數(shù)),floating(浮點(diǎn)數(shù)),point(指針),Boolean(布爾變量),CharacterorString(字符或字符串)。integer整數(shù)下邊給出的數(shù)據(jù)表示都是整數(shù)的例子:4,15,089,0xAD00整數(shù)長(zhǎng)度數(shù)據(jù)類型表示8bitsbyte16bitsshort32bitsint64bitslong
floating浮點(diǎn)數(shù)下邊給出的數(shù)據(jù)表示都是浮點(diǎn)數(shù)的例子:6.37,3.7E15,3e8
浮點(diǎn)數(shù)長(zhǎng)度數(shù)據(jù)類型表示32bitsfloat64bitsdouble
Boolean布爾變量下邊是布爾變量的兩種可能取值:truefalseCharacter字符下邊給出的都是字符的例子:a\\t(tab)\\u????(unicode)
String字符串下邊給出的都是字符串的例子:\"Thisisastringliteral\"\"中國(guó)科學(xué)院計(jì)算所\"數(shù)組你可以定義任意類型的數(shù)組.chars[];這是字符型數(shù)組;int[]array;這是整型數(shù)組;你還可以定義數(shù)組的數(shù)組.intblock[][]=newint[2][3];數(shù)組邊界在運(yùn)行時(shí)被檢測(cè),避免堆棧溢出和內(nèi)存崩潰.
在Java里,數(shù)組實(shí)際上是一個(gè)對(duì)象,數(shù)組有一個(gè)成員變量:length。你可以用這個(gè)成員函數(shù)來(lái)查看任意數(shù)組的長(zhǎng)度.inta[][]=newint[10][3]a.length/*10*/a[0].length/*3*/創(chuàng)建數(shù)組在Java里創(chuàng)建數(shù)組,你可使用兩種基本方法:一。創(chuàng)建一個(gè)空數(shù)組:intlist[]=newint[50];或你可以用初始數(shù)值填充數(shù)組.Stringnames[]={\"Chenji\",\"Yuan\",\"Chun\",\"Yang\"};相當(dāng)于下面功能:Stringnames[];names=newString[4];names[0]=newString(\"Chenji\");names[1]=newString(\"Yuan\");names[2]=newString(\"Chun\");names[3]=newString(\"Yang\");在編譯時(shí)你不能象下例那樣創(chuàng)建靜態(tài)數(shù)組。intname[50];//將產(chǎn)生一個(gè)編譯錯(cuò)誤你也不能用new操作去填充一個(gè)沒(méi)定義大小的數(shù)組。intname[];for(inti=0;i
3.1.5表達(dá)式
Java語(yǔ)言的表達(dá)式和C語(yǔ)言非常類似。運(yùn)算符運(yùn)算符(operator)優(yōu)先級(jí)從高到底排列如下:.[]()++--!~instanceof*/%+-\\==!=&^&&||?:
=op=,整數(shù)運(yùn)算符在整數(shù)運(yùn)算時(shí),如果操作數(shù)是long類型,則運(yùn)算結(jié)果是long類型,否則為int類型,絕不會(huì)是byte,short或char型。這樣,如果變量i被聲明為short或byte,i+1的結(jié)果會(huì)是int。如果結(jié)果超過(guò)該類型的取值范圍,則按該類型的值取模。單目整數(shù)運(yùn)算符是:運(yùn)算符操作-單目非~位補(bǔ)碼++加1--減1++運(yùn)算符用于表示直接加1操作。增量操作也可以用加運(yùn)算符和賦值操作間接完成。++lvalue(左值?copy;表示lvalue+=1,++lvalue也表示lvalue=lvalue+1(只要lvalue沒(méi)有副作用)。--運(yùn)算符用于表示減1操作。++和--運(yùn)算符既可以作為前綴運(yùn)算符,也可以做為后綴運(yùn)算符。雙目整數(shù)運(yùn)算符是:運(yùn)算符操作**+加-減*乘/除%取模&位與|位或^位異或=,==和!=產(chǎn)生boolean類型的數(shù)據(jù)。
布爾運(yùn)算符布爾(boolean)變量或表達(dá)式的組合運(yùn)算可以產(chǎn)生新的boolean值。單目運(yùn)算符!是布爾非。雙目運(yùn)算符&,|和^是邏輯AND,OR和XOR運(yùn)算符,它們強(qiáng)制兩個(gè)操作數(shù)求布爾值。為避免右側(cè)操作數(shù)冗余求值,用戶可以使用短路求值運(yùn)算符&&和||。用戶可以使用==和!=,賦值運(yùn)算符也可以用&=、|=、^=。三元條件操作符?:和C語(yǔ)言中的一樣。
浮點(diǎn)運(yùn)算符浮點(diǎn)運(yùn)算符可以使用常規(guī)運(yùn)算符的組合:如單目運(yùn)算符++、--,雙目運(yùn)算符+、-、*和/,以及賦值運(yùn)算符+=,-=,*=,和/=。此外,還有取模運(yùn)算:%和%=也可以作用于浮點(diǎn)數(shù),例如:a%b和a-((int)(a/b)*b)的語(yǔ)義相同。這表示a%b的結(jié)果是除完后剩下的浮點(diǎn)數(shù)部分。只有單精度操作數(shù)的浮點(diǎn)表達(dá)式按照單精度運(yùn)算求值,產(chǎn)生單精度結(jié)果。如果浮點(diǎn)表達(dá)式中含有一個(gè)或一個(gè)以上的雙精度操作數(shù),則按雙精度運(yùn)算,結(jié)果是雙精度浮點(diǎn)數(shù)。
數(shù)組運(yùn)算符數(shù)組運(yùn)算符形式如下:[]可給出數(shù)組中某個(gè)元素的值。合法的取值范圍是從0到數(shù)組的長(zhǎng)度減1。取值范圍的檢查只在運(yùn)行時(shí)刻實(shí)。運(yùn)算符以String對(duì)象實(shí)現(xiàn)。運(yùn)算符\"+\"完成并操作,如果必要?jiǎng)t自動(dòng)把操作數(shù)轉(zhuǎn)換為String型。如果操作數(shù)是一個(gè)對(duì)象,它可定義一個(gè)方法toString()返回該對(duì)象的String方式,例如floata=1.0print(\"Thevalueofais\"+a+\"\\n\");+運(yùn)算符用到?reg;上的例子Strings=\"a=\"+a;+=運(yùn)算符也可以用于String。注意,左邊(下例中的s1)僅求值一次。s1+=a;//s1=s1+a//若a非String型,自動(dòng)轉(zhuǎn)換為String型。對(duì)象運(yùn)算符雙目運(yùn)算符instanceof測(cè)試某個(gè)對(duì)象是否是指定類或其子類的實(shí)例。例如:if(myObjectinstanceofMyClass){MyClassanothermyObject=(MyClass)myObject;…}是判定myObject是否是MyClass的實(shí)例或是其子類的實(shí)例。強(qiáng)制和轉(zhuǎn)換Java語(yǔ)言和解釋器限制使用強(qiáng)制和轉(zhuǎn)換,以防止出錯(cuò)導(dǎo)致系統(tǒng)崩潰。整數(shù)和浮點(diǎn)數(shù)之間可以來(lái)回
強(qiáng)制轉(zhuǎn)換,但整數(shù)不能強(qiáng)制轉(zhuǎn)換成數(shù)組或?qū)ο?。?duì)象不能被強(qiáng)制為基本類型。
3.1.6Java流控制
下面幾個(gè)控制結(jié)構(gòu)是從C語(yǔ)言借鑒的。分支結(jié)構(gòu)
if/else分支結(jié)構(gòu)if(Boolean){statemanets;}else{statements;}
switch分支結(jié)構(gòu)switch(expr1){caseexpr2:statements;break;caseexpr3:statements;break;default:statements;break;}
循環(huán)結(jié)構(gòu)for循環(huán)結(jié)構(gòu)for(initexpr1;testexpr2;incrementexpr3){statements;}
While循環(huán)結(jié)構(gòu)While(Boolean){statements;}
Do循環(huán)結(jié)構(gòu)do{statements;}while(Boolean);
一般順序控制break[label]continue[label]reutrnexpr;label:statement;
for循環(huán)例子下面是一個(gè)程序例子,畫幾條線,分別用紅,綠,藍(lán)顏色,這段程序可能是Java函數(shù)的一部分:intcount;for(count=1;count
3.2Java變量和函數(shù)的實(shí)例
Java的類包含變量和函數(shù)。數(shù)據(jù)變量可以是一些原始的類型,如int,char等。成員函數(shù)是一些可執(zhí)行的過(guò)程。例如,下面程序里:publicclassClassOne{inti;publicClassOne(){i=10;}publicvoidAdd_i(intj){i=i+j;}}ClassOne包含一個(gè)變量i和兩個(gè)成員函數(shù),ClassOne(intfirst)和Add_i(intj)。
成員函數(shù)成員函數(shù)是一些可被其它類或自己類調(diào)用的處理子程序。一個(gè)特殊的成員函數(shù)叫構(gòu)造函數(shù),這個(gè)函數(shù)名稱一般與本類名程相同。它沒(méi)有返回值。構(gòu)造函數(shù)和成員函數(shù)當(dāng)你在Java里定義一個(gè)類時(shí),你可定義一個(gè)或多個(gè)可選的構(gòu)造函數(shù),當(dāng)創(chuàng)建本類的一個(gè)對(duì)象時(shí)用某一個(gè)構(gòu)造函數(shù)來(lái)初始化本對(duì)象。用前面的程序例子來(lái)說(shuō)明,當(dāng)ClassOne類創(chuàng)建一個(gè)新實(shí)例時(shí),所有成員函數(shù)和變量被創(chuàng)建(創(chuàng)建實(shí)例)。構(gòu)造函數(shù)被調(diào)用。ClassOnemc:mc=newClassOne();
關(guān)鍵詞new用來(lái)創(chuàng)建一個(gè)類的實(shí)例,一個(gè)類用new初始化前并不占用內(nèi)存,它只是一個(gè)類型定義,當(dāng)mc對(duì)象初始化后,mc對(duì)象里的i變量等于10。你可以通過(guò)對(duì)象名來(lái)引用變量i。(有時(shí)稱為實(shí)例變量)mc.i++;//mc實(shí)例變量加1因?yàn)閙c有ClassOne類的所有變量和成員函數(shù),我們可以使用同樣的語(yǔ)法來(lái)調(diào)用成員函數(shù)Add_i:Add_i(10);現(xiàn)在mc.i變量等于21.
結(jié)束函數(shù)Java并不支持析構(gòu)函數(shù)(C++里的定義),因?yàn)閖ava本身提供對(duì)象無(wú)用時(shí)自動(dòng)清除的功能,同時(shí)它也提供了一個(gè)自動(dòng)拉圾箱的成員函數(shù),在清除對(duì)象時(shí)被調(diào)用:Protectedvoidfinalize(){close();}
3.3對(duì)象
有效范圍和廢物自動(dòng)回收對(duì)象有一定的生命期并在它的生命期間使用資源,當(dāng)一個(gè)對(duì)象不再被使用時(shí),它應(yīng)釋放內(nèi)存,避免內(nèi)存溢出。在Java里,收集和釋放內(nèi)存是一個(gè)叫自動(dòng)廢品回收站的線程的責(zé)任。這個(gè)線程監(jiān)視對(duì)象有效范圍并給一個(gè)走出有效范圍的對(duì)象作上標(biāo)識(shí)。
例如:Strings;//沒(méi)有分配內(nèi)存s=newString(\"oldstring\");//分配內(nèi)存s=\"newstring\";//重新分配內(nèi)存(創(chuàng)建新對(duì)象)我們將在以后訪問(wèn)String類時(shí)將更加明白它的工作過(guò)程,但它的快速工作過(guò)程是這樣的:1.創(chuàng)建一個(gè)新的String類對(duì)象并填充以\"oldstring\"2.創(chuàng)建另一個(gè)String對(duì)象并填充以\"newstring\"注意我們創(chuàng)建了兩個(gè)對(duì)象。Stirng對(duì)象\"oldstring\"Stirng對(duì)象\"newstring\"在第三條語(yǔ)句里,第一個(gè)包括\"oldstring\"的叫做s的對(duì)象已走出了有效范圍,沒(méi)有任何方法可以再訪問(wèn)他,我們現(xiàn)在有一個(gè)新的對(duì)象也叫s,包含\"newstring\"。在下一個(gè)廢品回收線程,前一個(gè)對(duì)象將被標(biāo)識(shí)并清除。
3.4子類
子類是利用存在的對(duì)象創(chuàng)建一個(gè)新對(duì)象的機(jī)制,比如,如果你有一個(gè)Horse類,你可以創(chuàng)建一個(gè)Zebra子類,Zebra是Horse的一種。
classZebraextendsHorse{intnumber_OF_stripes:}關(guān)鍵詞extends來(lái)定義對(duì)象有的子類.Zebra是Horse的子類。Horse類里的所有特征都將拷貝到Zebra類里,而Zebra類里可以定義自己的成員函數(shù)和實(shí)例變量。Zebra稱為Horse的派生類或繼承。另外,你也許還想覆蓋基類的成員函數(shù)。用ClassOne說(shuō)明,下面是一個(gè)派生類覆蓋Add_i功能的例子.
importClassOne;publicclassNewClassextendsClassOne{publicvoid
Add_i(intj){i=i+(j/2);}}
當(dāng)NewClass類的實(shí)例創(chuàng)建時(shí),變量i初始化值為10,但調(diào)用Add_i產(chǎn)生不同的結(jié)果。NewClassmnc;mnc=newNewClass();mnc.Add_i(10);訪問(wèn)控制Java里當(dāng)你創(chuàng)建一個(gè)新類時(shí),你可以標(biāo)明變量和成員函數(shù)的訪問(wèn)層次。
publicpublicvoidAnyOneCanAccess(){}public實(shí)例變量和成員函數(shù)可以任意其它類調(diào)用。
protectedprotectedvoidOnlySubClasses(){}protected實(shí)例變量和成員函數(shù)只能被其子類調(diào)用.
privateprivateStringCreditCardNumber;private實(shí)例變量和成員函數(shù)只能在本類里調(diào)用.
friendlyvoidMyPackageMethod(){}缺省的,如果沒(méi)有定義任何防火控制,實(shí)例變量或函數(shù)缺省定義成friendly,意味著可以被本包里的任意對(duì)象防問(wèn),但其它包里的對(duì)象不可防問(wèn)。靜態(tài)成員函數(shù)和變量有?copy;時(shí)候,你創(chuàng)建一個(gè)類,希望這個(gè)類的所有實(shí)例都公用一個(gè)變量。也就是說(shuō),所有這個(gè)類的對(duì)象都只有實(shí)例變量的同一個(gè)拷貝。這種方法的關(guān)鍵詞是static,例如:classBlock{staticintnumber=50;}
所有從Block類創(chuàng)建的對(duì)象的number變量值都是相同的。無(wú)任在哪個(gè)對(duì)象里改變了number的值,所有對(duì)象的number都跟著改變。同樣的,你可以定義static成員函數(shù),但這個(gè)成員函數(shù)不能訪問(wèn)非static函數(shù)和變量。classBlock{staticintnumber=50;intlocalvalue;staticvoidadd_local(){localvalue++;//沒(méi)有運(yùn)行}staticvoidadd_static(){number++;//運(yùn)行}}
3.5this和super
訪問(wèn)一個(gè)類的實(shí)例變量時(shí),this關(guān)鍵詞是指向這個(gè)類本身的指針,在前面ClassOne例子中,我們可以增加構(gòu)造函數(shù)如下:
publicclassClassOne{inti;publicClassOne(){i=10;}
publicClassOne(intvalue)this.i=value;}
publicvoidAdd_i(intj){i=i+j;}}
這里,this指向ClassOne類的指針。如果在一個(gè)子類里覆蓋了父類的某個(gè)成員函數(shù),但又想調(diào)用父類的成員函數(shù),你可以用super關(guān)鍵詞指向父類的成員函數(shù)。
importClassOne;publicclassNewClassextendsClassOne{publicvoidAdd_i(intj){i=i+(j/2);super.Add_i(j);}}
下面程序里,i變量被構(gòu)造函數(shù)設(shè)成10,然后15,最后被父類(ClassOne)設(shè)成25。NewClassmnc;mnc=newNewClass();mnc.Add_i(10);
3.6類的類型
至今為止,我用在類前面只用了一個(gè)public關(guān)鍵詞,其實(shí)它有下面4種選擇:abstract一個(gè)abstract類必須至少有一個(gè)虛擬函數(shù),一個(gè)abstract類不能直接創(chuàng)建對(duì)象,必須繼承子類后才能。
final一個(gè)final類聲明了子類鏈的結(jié)尾,用final聲明的類不能再派生子類。publicpublic類能被其它的類訪問(wèn)。在其它包里,如果想使用這個(gè)類必須先import,則它只能在它定義的package里使用。synchronicable這個(gè)類標(biāo)識(shí)表示所有?copy;類的成員函數(shù)都是同步的。
3.7抽象類
面向?qū)ο蟮囊粋€(gè)優(yōu)點(diǎn)就是能夠定義怎樣使用這個(gè)類而不必真正定義好成員函數(shù)。如果程序由不同的用戶實(shí)現(xiàn)時(shí)是很有用的,這不需用戶使用相同的成員函數(shù)名。
在java里Graphics類里一個(gè)abstract類的例子如下:publicabstractclassGraphics{publicabstractvoiddrawLine(intx1,inty1,intx2,inty2);publicabstractvoiddrawOval(intx,inty,intwidth,intheight);publicabstractvoiddrawRect(intx,inty,intwidth,intheight);...}
在Graphics類里聲明了幾個(gè)成員函數(shù),但成員函數(shù)的實(shí)際代碼是在另外一?copy;地方實(shí)現(xiàn)的。
publicclassMyClassextendsGraphics{publicvoiddrawLine(intx1,inty1,intx2,inty2){}}
當(dāng)一個(gè)類包含一個(gè)abstract成員函數(shù),這個(gè)類必須定義為abstract類。然而并不是abstract類的所有的成員函數(shù)都是abstract的。Abstract類不能有私有成員函數(shù)(它們不能被實(shí)現(xiàn)),也不能有靜態(tài)成員函數(shù)。
3.8接口
當(dāng)你確定多個(gè)類的操作方式都很相象時(shí),abstract成員函數(shù)是很有用的。但如果你需要使用這?copy;abstract成員函數(shù),必須創(chuàng)建一個(gè)新類,這樣有時(shí)很繁瑣。接口提?copy;了一種抽象成員函數(shù)的有利方法。一個(gè)接口包含了在另一個(gè)地方實(shí)現(xiàn)的成員函數(shù)的收集。成員函數(shù)在接口里定義為public和abstract。接口里的實(shí)例變量是public,static和final。接口和抽象的主要區(qū)別是一個(gè)接口提?copy;了封裝成員函數(shù)協(xié)議的方法而不必強(qiáng)迫用戶繼承類。例子:publicinterfaceAudiClip{//Startplayingtheclip.voidplay();//Playtheclipinaloop.voidloop();//Stopplayingtheclipvoidstop();}
想使用AudioClip接口的類使用implenents關(guān)鍵詞來(lái)提?copy;成員函數(shù)的程序代碼。classMyClassimplementsAudioClip{voidplay(){}}
優(yōu)點(diǎn)一個(gè)接口類可以被任意多的類實(shí)現(xiàn),每個(gè)類可以共享程序接口而不必關(guān)心其它類是怎樣實(shí)現(xiàn)的。classMyOtherClassimplementsAudioClip{voidstop(){}...}內(nèi)部成員函數(shù)Java還提?copy;了調(diào)用C和C++函數(shù)的方法。用native關(guān)鍵詞來(lái)定義C和C++的函數(shù)。publicclassDate{intnow;publicDate(){now=time();}privatenativeinttime();static{System.loadLibrary(\"time\");}}一?copy;Java代碼寫好后,就需要以下步驟執(zhí)行:1.用javah來(lái)創(chuàng)建頭文件(.h)2.用javah來(lái)創(chuàng)建stub文件3.用C和C++寫native成員函數(shù)的代碼4.編譯stub文件和.C文件成一個(gè)動(dòng)態(tài)可加載庫(kù)5.用java運(yùn)行java程序或appletviewer運(yùn)行applet注意:Native成員函數(shù)超出了類的范圍。
3.9包(Packages)
包(Package)由一組類(class)和界面(interface)組成。它是管理大型名字空間,避免名字沖突的工具。每一個(gè)類和界面的名字都包含在某個(gè)包中。按照一般的習(xí)慣,它的名字是由\".\"號(hào)分隔的單詞構(gòu)成,第一個(gè)單詞通常是開發(fā)這個(gè)包的組織的名稱。
定義一個(gè)編譯單元的包編譯單元的包由package語(yǔ)句定義。如果使用package語(yǔ)句,編譯單元的第一行必須無(wú)空格,也無(wú)注釋。其格式如下:packagepackageName;若編譯單元無(wú)package語(yǔ)句,則該單元被置于一個(gè)缺省的無(wú)名的包中。使用其它包中的類和界面在Java語(yǔ)言里提?copy;一個(gè)包可以使用另一個(gè)包中類和界面的定義和實(shí)現(xiàn)的機(jī)制。用import關(guān)鍵詞來(lái)標(biāo)明來(lái)自其它包中的類。一個(gè)編譯單元可以自動(dòng)把指定的類和界面輸入到它自己的包中。在一個(gè)包中的代碼可以有兩種方式來(lái)定義來(lái)自其它包中的類和界面:*在每個(gè)引用的類和界面前面給出它們所在的包的名字;//前綴包名法acme.project.FooBarobj=newacme.project.FooBar();*使用import語(yǔ)句,引入一個(gè)類或一個(gè)界面,或包含它們的包。引入的類和界面的名字在當(dāng)前的名字空間可用。引入一個(gè)包時(shí),則該包所有的公有類和界面均可用。其形式如下://從acme.project引入所有類importacme.project.*;這個(gè)語(yǔ)句表示acme.project中所有的公有類被引入當(dāng)前包。以下語(yǔ)句從acme.project包中進(jìn)入一個(gè)類Employec_List。//從acme.project而引入Employee_Listimportacme.project.Employee_list;Employee_Listobj=newEmployee_List();在使用一個(gè)外部類或界面時(shí),必須要聲明該類或界面所在的包,否則會(huì)產(chǎn)生編譯錯(cuò)誤。import(引用)類包(classpackage)用import關(guān)鍵詞調(diào)入,指定package名字如路徑和類名,用*匹配符可以調(diào)入多于一個(gè)類名。
importjava.Date;importjava.awt.*;
如果java源文件不包含package,它放在缺省的無(wú)名package。這與源文件同目錄,類可以這樣引入:importMyClass。
Java系統(tǒng)包:Java語(yǔ)言提?copy;了一個(gè)包含窗口工具箱,實(shí)用程序,一般I/O,工具和網(wǎng)絡(luò)功能的包。
java.applet這個(gè)包包含量了一?copy;設(shè)計(jì)applet的類,用一個(gè)類Applet和三個(gè)接口.AppletContext;AppletStub;和AudioClip.
java.awt另一個(gè)窗口工具箱包.awt,包含了一?copy;產(chǎn)生裝飾物和GUI成員的類。這個(gè)package包括:
Button,Checkbox,Choice,Component,Graphics,Menu,Pane1,TextArea和TextField。
java.ioI/Opackage包含文件輸入/輸出類,F(xiàn)ileInputStream和FileOutputStream.
java.lang這個(gè)包包含Java語(yǔ)言類,包含:對(duì)象,線程,異常出口,系統(tǒng),整數(shù),原點(diǎn),數(shù)學(xué),字符等。
java.net這個(gè)類支持TCP/IP網(wǎng)絡(luò)協(xié)議,并包含Socket類,URL和URL相聯(lián)系的類。
java.util這個(gè)類包含一?copy;程序的同步類,它包含Date,Dictionary類等。
3.10異常
當(dāng)在Java程序中發(fā)生一個(gè)錯(cuò)誤時(shí),例如:一個(gè)變?cè)闹捣欠ǎa會(huì)發(fā)現(xiàn)這個(gè)錯(cuò)誤,并引發(fā)一個(gè)異常(exception)。在缺省的情況下,異常會(huì)輸出一個(gè)錯(cuò)誤消息,然后中止線程的執(zhí)行。但是,程序自己可以定義異常處理段(exceptionhandler)來(lái)截獲(catch)異常,并從錯(cuò)誤中恢復(fù)。有一?copy;異常是由Java解釋器在運(yùn)行時(shí)刻引發(fā)的。實(shí)際上,任何類都可以定義屬于自己的異常,并使用throw語(yǔ)句引發(fā)它們。一個(gè)throw(引發(fā)?copy;語(yǔ)句是由throw關(guān)鍵字和一個(gè)對(duì)象構(gòu)成。按常規(guī),該對(duì)象應(yīng)該是Exception類的實(shí)例或其子類的實(shí)例。throw語(yǔ)句會(huì)引起執(zhí)行轉(zhuǎn)向相應(yīng)的異常處理段。當(dāng)一個(gè)throw語(yǔ)句執(zhí)行時(shí),它下面的所有代碼不再執(zhí)行了,它所在的方法也不再返回值。下面的例子將演示如何創(chuàng)建一個(gè)Exception的子類,然后引發(fā)一個(gè)異常。classMyExceptionextendsException{}classMyClass{voidoops(){if(/*不出現(xiàn)錯(cuò)誤*/){…}else{/*出錯(cuò)*/}else{/*出錯(cuò)*/thrownewMyException();}}}為了定義一個(gè)異常處理段,程序必須用try語(yǔ)句把可能產(chǎn)生異常的代碼成組。在try語(yǔ)句后面跟上一個(gè)或多個(gè)catch(截獲?copy;語(yǔ)句,每個(gè)異常對(duì)應(yīng)一個(gè)catch語(yǔ)句。每個(gè)catch語(yǔ)句中包含著異常處理段。例如:try{p.a=10;}catch(NullPointerExceptione){println(\"pwasnull\");}catch(Exceptione){println(\"othererrorsoccured\");}catch(Objectobj){println(\"Whothrewthatobject?\");}catch語(yǔ)句和一個(gè)方法定義類似,只不過(guò)該方法只有一個(gè)參數(shù),且無(wú)返回類型。參數(shù)可以是一個(gè)類或一個(gè)界面。當(dāng)一個(gè)異常發(fā)生時(shí),嵌套的try/catch語(yǔ)句會(huì)尋找出與該異常類相匹配的參數(shù)。如果一個(gè)參數(shù)和指定異常匹配則:*該參數(shù)和指定的異常是同一個(gè)類,或*該參數(shù)是指定異常的子類,或*如果參數(shù)是一個(gè)界面,指定異常類實(shí)現(xiàn)了這個(gè)界面。第一個(gè)參數(shù)和異常匹配的try/catch語(yǔ)句,則與其匹配的catch語(yǔ)句執(zhí)行。在catch語(yǔ)句執(zhí)行完后,程序的執(zhí)行被恢復(fù)。但已不可能恢復(fù)到異常發(fā)生處再次執(zhí)行。例如:print(\"now\");try{print(\"is\");thrownewMyException();print(\"a\");}catch(MyExceptione){print(\"the\");}print(\"time\\n\");打印為\"nowisthetime\"。正如這個(gè)例子所示,異常應(yīng)該主要用于錯(cuò)誤處理,若用于其它方面會(huì)使代碼晦澀難?reg;。異常處理段是可以嵌套的,允許異常處理可以發(fā)生在多個(gè)地方。嵌套異常處理通常用于當(dāng)?shù)谝粋€(gè)處理程序無(wú)法完全從錯(cuò)誤中恢復(fù)過(guò)來(lái)的時(shí)候,而不得不執(zhí)行一?copy;清除代碼。為了把異常處理控制傳遞給更高層的處理段,可以再一次對(duì)截獲對(duì)象實(shí)?copy;throw操作。注要再次實(shí)throw異常的方法,throw語(yǔ)句執(zhí)行完后,會(huì)終止執(zhí)行。try{f.open();}catch(Exceptione){f.close();throwe;}定局語(yǔ)句finally(定局?copy;語(yǔ)句是用于保證無(wú)論在異常是否發(fā)生的情況下,某?copy;代碼被執(zhí)行。下例說(shuō)明finally語(yǔ)句的用法:try{//做某?copy;動(dòng)作;}finally{//此后清除;}和以下代碼類似try{//做某?copy;動(dòng)作}catch(Objecte){//此后清除;throwe;}}//此后清除;即使try塊中包含return,break,continue,throw語(yǔ)句,finally語(yǔ)句也會(huì)被執(zhí)行。例如:下面的代碼\"finally\"總是被輸出,而\"aftertry\"僅在a!=10時(shí)被輸出。try{if(a==10){return;}}finally{print(\"finally\\n\");}print(\"aftertry\\n\");運(yùn)行時(shí)刻異常本節(jié)列出的清單是Java解釋器引發(fā)的各種異常。當(dāng)運(yùn)行時(shí)刻發(fā)現(xiàn)各種錯(cuò)誤,由解釋器引發(fā)異常。ArithmeticException如果程序試圖除0,或用0取模,會(huì)產(chǎn)生ArithmeticException(算術(shù)異常?copy;,其它算術(shù)操作不會(huì)產(chǎn)生異常。有關(guān)Java如何處理其它算術(shù)錯(cuò)誤的信息,見(jiàn)\"整數(shù)運(yùn)算符\"和\"浮點(diǎn)運(yùn)算符\"兩節(jié)。例如:下面的代碼將會(huì)引發(fā)ArithmeticException異常:classArith{publicstaticvoidmain(Stringargs[]){intj=0;j=j/j;}}NullPointerException當(dāng)程序試圖訪問(wèn)一個(gè)空對(duì)象中的變量或方法,或一個(gè)空數(shù)組中的元素時(shí)則引發(fā)NullPointerException(空指針異常?copy;。例如,訪問(wèn)長(zhǎng)度為0的數(shù)組a[0]。有以下類聲明,運(yùn)行時(shí)會(huì)引發(fā)NullPointerException異常:classNull{publicstaticvoidmain(Stringargs[]){Stringo=null;inta[]=null;o.length();a[0]=0;}}有趣的是,如果我們引發(fā)一個(gè)空對(duì)象,也會(huì)產(chǎn)一NullPointerException異常?! ncompatibleClassChangeException當(dāng)一個(gè)類的定義被改變,而引用該類的其它類沒(méi)有被重新編譯時(shí),會(huì)產(chǎn)生這一異常。有四種類更改會(huì)導(dǎo)致運(yùn)行時(shí)刻引發(fā)IncompatibleClassChangException異常。*一個(gè)類中的變量聲明由static變成非static,而其它訪問(wèn)該類這一變量的類沒(méi)有被重新編譯。*一個(gè)類中的變量聲明由非static變成static,而其它訪問(wèn)該類這一變量的類沒(méi)有被重新編譯。*類中聲明的某個(gè)域被刪除,而其它訪問(wèn)該域的類沒(méi)有被重新編譯。*類中聲明的某個(gè)方法被刪除,而其它訪問(wèn)該方法的類沒(méi)有被重新編譯。
ClassCastException如果試圖把對(duì)象o強(qiáng)制成ClassC,而o既不是ClassC的實(shí)例,也不是ClassC子類的實(shí)例,這時(shí)便會(huì)產(chǎn)生ClassCastException。classClassCast{publicstaticvoidmain(Stringargs[]){Objecto=newObject();Strings=(string)o;s.length();}}}NagativeArraySizeException如果一個(gè)數(shù)組的長(zhǎng)度是負(fù)數(shù),則會(huì)引發(fā)NagativeArraySizeException(數(shù)組負(fù)下標(biāo)?copy;異常。例如下面類定義的代碼在運(yùn)行時(shí)引發(fā)這一異常:classNegArray{publicstaticvoidmain(Stringargs[]){inta[]=newint[-1];a[0]=0;}}
OutOfMemoryException當(dāng)系統(tǒng)無(wú)法再向應(yīng)用程序提?copy;內(nèi)存時(shí),會(huì)引發(fā)OutOfMemoryException(內(nèi)存溢出?copy;異常。這種異常只能出現(xiàn)在創(chuàng)建新對(duì)象的時(shí)候,即new被調(diào)用的時(shí)候。例如,下面一段代碼在運(yùn)行時(shí)刻會(huì)引發(fā)OutOfMemoryException異常:classLink{inta[]=newint[1000000];Linkl;}ClassOutOfMem
{publicstaticvoidmain(Stringargs[]){publicstaticvoidmain(Stringargs[]){Linkroot=newlink();Linkcur=root;while(true){cur.l=newLink();cur=cur.l;}}}NoClassDefFoundException如果一個(gè)類被引用,但在運(yùn)行時(shí)刻,系統(tǒng)沒(méi)有找到被引用的類,這時(shí)會(huì)引發(fā)NoClassDefFoundException(未找到類定義?copy;異常。例如,NoClass
的聲明如下:classNoClass{publicstaticvoidmain(Stringargs[]){Cc=newC();}}當(dāng)NoClass運(yùn)行時(shí),如果解釋器找不到C類,則會(huì)產(chǎn)生NoClassDefFoundException。注意,在NoClass被編譯時(shí)C類一定要存在。
IncompatibleTypeException如果試圖為一界面作實(shí)例,則會(huì)引發(fā)IncompatibleTypeException(類型不兼容?copy;異常。例如,下面的代碼會(huì)引發(fā)一個(gè)IncompatibleTypeException。InterfaceI{}classIncompType{publicstaticvoidmain(Stringargs[]){Ir=(I)new(\"I\");}}ArrayIndexOutOfBoundsException試圖訪問(wèn)數(shù)組中的一個(gè)非法元素時(shí),會(huì)引發(fā)ArrayIndexOutOfBoundsException(數(shù)組索引越界?copy;異常。例如:ClassArrayOut{publicstaticvoidmain(Stringargs[]){inta[]=newint[0];a[0]=0;}}publicstaticvoidmain(Stringargs[]){inta[]=newint[0];a[0]=0;}}UnsatisfiedLinkException如果一個(gè)方法被聲明為本機(jī),但該方法在運(yùn)行時(shí)刻卻不能連接到一個(gè)例程體上去時(shí),會(huì)產(chǎn)生UnsatisfiedLinkException(無(wú)法連接?copy;異常。例如:ClassNoLink{staticnativevoidfoo();publicstaticvoidmain(Stringargs[]){foo();}}InternalExceptionInternalException(內(nèi)部?copy;異常是不能被引發(fā)的。只有在運(yùn)行失敗作一致性檢查時(shí),才會(huì)引發(fā)這個(gè)異常。
本章小結(jié)
1.Java語(yǔ)言的基本結(jié)構(gòu)象C/C++。2.Java語(yǔ)言的源程序代碼由一個(gè)或多個(gè)編譯單元(compilationunit)組成。