包(package)是類和接口的集合,利用包可以把常用的類或功能相似的類放在一個包中。Java還提供了系統(tǒng)包。
接口(interface)解決了Java不支持多重繼承的問題,可以通過實(shí)現(xiàn)多個接口達(dá)到與多重繼承相同的功能。
6.1 包
包是Java提供的一種區(qū)別類名空間的機(jī)制,是類的邏輯組織形式,一個包對應(yīng)一個文件夾,包中還可以有包,稱為包等級。
當(dāng)源程序中沒有聲明類所在的包時,Java將類放在默認(rèn)包中,即運(yùn)行編譯器的當(dāng)前文件夾中。這時不能出現(xiàn)重復(fù)的類名。
6.1.1 Java的系統(tǒng)包
Java提供了大量的類,為便于管理和使用,分為不同的包。這些包又稱類庫或API包,所謂API(application program interface)即應(yīng)用程序接口。API包一方面提供豐富的類與方法供大家使用,如畫圖形、播放聲音等,另一方面又負(fù)責(zé)和系統(tǒng)軟硬件打交道,把用戶程序的功能圓滿實(shí)現(xiàn)。
許多Java API包都以“java.”開頭,以區(qū)別用戶創(chuàng)建的包。
1.java.lang
是Java語言的基礎(chǔ)類庫,包含基本數(shù)據(jù)類型、數(shù)學(xué)函數(shù)、字符串等。這是唯一自動引入每個Java程序的類庫。Java.lang包中包含有以下主要類:
?。?)Object 類:是Java類層次的根,所有其他類都是由Object類派生出來的。其定義的方法,在其他類中都能使用。如:復(fù)制方法clone( ),獲得對象的類getClass( )方法,兩個對象是否相等的equals( )方法,將對象輸出為字符串的toString( )方法等
在比較兩個變量、兩個值、對象與變量相等時使用“==”,在比較兩個對象相等時使用equals()
char ch='a' ;if(ch=='a'||ch=='A');
String S1="123" ,S2="123" ;
if(S1==S2)
System.out.println(S1.equals(S2)); // 與S1= =S2效果一樣,true
System.out.println(ch.equals(S2)); //錯
(2)數(shù)據(jù)類型包裝類:
?。?)數(shù)學(xué)Math類:如常數(shù)E和PI,數(shù)學(xué)方法sin和cos等,Math是最終類,其中的數(shù)據(jù)和方法都是靜態(tài)的(直接用類名引用)
?。?)字符串String和StringBuffer類
(5)系統(tǒng)System類:提供訪問系統(tǒng)資源和標(biāo)準(zhǔn)輸入輸出方法
如:System.out.print (<輸出量>)
System.exit(0) // 結(jié)束當(dāng)前程序的運(yùn)行
System類的變量和方法都是final和static
?。?)運(yùn)行時Runtime類:可以直接訪問運(yùn)行時的資源
如:totalMemory方法可返回系統(tǒng)內(nèi)存總量
freeMemory方法返回內(nèi)存剩余空間
?。?)線程Thread類
(8)類操作class和classLoader類:
如: this.getClass( ).getName( ) // 返回當(dāng)前對象的類名
?。?)錯誤和異常處理類:Throwable , Exception , Error
2.java.util包
提供了實(shí)現(xiàn)各種低級實(shí)用功能的類,如日期類、集合類等
(1)Date類:構(gòu)造方法Date()可獲得系統(tǒng)當(dāng)前日期和時間
?。?)Calender類:將Date對象的數(shù)據(jù)轉(zhuǎn)換成YEAR , MONTH , DATE , DATE_OF_WEEK等常量,Calender類沒有構(gòu)造方法,可用getInstance方法創(chuàng)建一個實(shí)例,再調(diào)用get方法和常量獲得日期或時間的部分值。
如:Calender now=Calender.getInstance( ); // 創(chuàng)建類Calendar的實(shí)例,并獲得系統(tǒng)日期和時間
int year=now.get(Calender.YEAR) ; // 用get方法得到當(dāng)前年份
GregorianCalendar類是Calender類的子類,實(shí)現(xiàn)標(biāo)準(zhǔn)的Gregorian日歷
?。?)隨機(jī)數(shù)Random類
3.java.io包
是Java語言的輸入輸出類庫,Java語言的文件操作都是由該類庫中的輸入輸出類(FileInputStream和FileOutputStream)實(shí)現(xiàn)的,java.io包除了包含標(biāo)準(zhǔn)輸入、輸出類外,還有緩存流、過濾流、管道流和字符串類等
4.java.net包
支持TCP/IP網(wǎng)絡(luò)協(xié)議,并包含Socket類及URL和URL相聯(lián)系的類
5.java.awt包
提供了創(chuàng)建圖形用戶界面的全部工具。如:窗口、對話框、按鈕、復(fù)選框、列表、菜單、滾動條和文本區(qū)等類;用于管理組件排列的布局管理器類Layout;以及常用顏色類Color、字體類Font。Java.awt.event類庫用來處理各種不同類型的事件。
6.java.applet包
是所有小應(yīng)用程序的基礎(chǔ)類庫。它只包含了一個Applet類和三個接口AppletContext , AppletStub , AudioClip,所有小應(yīng)用程序都是從該類中派生的。
7.java.security包
包括java.security.acl和java.security.interfaces子類庫,利用這些類可對Java程序進(jìn)行加密,設(shè)定相應(yīng)的安全權(quán)限等。
6.1.2 包的引用
1.導(dǎo)入包語句
格式:import <包名1>[.<包名2>……] .<類名>|* ;
說明:如果有多個包或類,用“.”分割,“*”表示包中所有的類。
例: import java.applet.Applet // 導(dǎo)入java.applet包中的Applet類
import java.awt.* // 導(dǎo)入java.awt包中的所有類
java.lang包是系統(tǒng)自動隱含導(dǎo)入
2.包的路徑
由于Java使用文件系統(tǒng)來存儲包和類,類名就是文件名,包名就是文件夾名,設(shè)置環(huán)境變量用classpath方法
6.1.2 聲明自定義包
1.創(chuàng)建自定義包
格式: package <包名>
說明:(1)聲明包語句必須添加在源程序的第一行,表示該文件的全部類都屬于這個包
?。?)可以在不同的文件中使用相同的聲明語句,可將不同文件中的類都包含在相同的包中
?。?)若在程序中沒有聲明包,類就放在默認(rèn)的包中,這個包沒有名字,默認(rèn)包適用于小的程序。
例:見P108 YMD.java文件內(nèi)容:
package Mypackage; // 聲明一個Mypackage包,區(qū)分大小寫
import java.util.*;
public class YMD{
private int year,month,day;
public static void main(String []args) {}
public YMD(int y, int m ,int d){
year=y;
month=(((m>=1)&(m<=12))?m:1);
day=(((d>=1) & (d<=31))?d:1); }
public YMD(){
this(0,0,0); }
public static int thisyear(){
return Calendar.getInstance().get(Calendar.YEAR); }//獲得當(dāng)年的年份
public int year(){
return year; }
public String toString(){
return year+"-"+month+"-"+day; //轉(zhuǎn)化為字符串
}}
說明:建立Mypackage(區(qū)分大小寫)文件夾,并將YMD.class復(fù)制該文件夾下
*******************************************
P3.java文件內(nèi)容:
import Mypackage.YMD;
public class P3{
private String name;
private YMD birth;
public static void main(String args[]){
P3 a=new P3("張弛",1990,1,11);
a.output();}
public P3(String n1,YMD d1){
name=n1;
birth=d1; }
public P3(String n1,int y,int m,int d){
this(n1,new YMD(y,m,d)); //初始化變量與對象,調(diào)用上一個構(gòu)造方法}
public int age()
{return YMD.thisyear()-birth.year(); //計(jì)算年齡 }
public void output(){
System.out.println("姓名: "+name);
System.out.println("出生年齡: "+birth.toString());
System.out.println("今年年齡: "+age());
}}
2.設(shè)置包的路徑
用自定義包名建立一個文件夾,如:c:\ Mypackage
設(shè)置路徑:set classpath=. ; c:\j2sdk1.4.2 ; c:\mypackage
以后其它類使用自定義包里的類用命令:import Mypackage.*
3.創(chuàng)建包等級
格式: package <包名1>[.<包名2>][.<包名3>][.<……>]
4.包的訪問權(quán)限
同一個類中
同一個包中
不同包中的子類
不同包中的非子類
private
√
protected
√
√
√
public
√
√
√
√
friendly
√
√
5.編譯和運(yùn)行包(補(bǔ)充)
例:package p1;
public class SC{
public static void main(String args[]){
System.out.println("演習(xí)!"); }}
操作要求::
(1)編譯文件方法一:javac SC.java
?。?)新建p1文件夾,將SC.class存入其中;
?。?)在p1文件夾的上一級文件夾中運(yùn)行 java p1.SC
說明:因?yàn)镾C.class存在p1包中,對它的引用應(yīng)是: p1.SC.class,所以在p1目錄下運(yùn)行java SC則錯,java p1.SC也錯,必須退到上一級,運(yùn)行java p1.SC才正確。
編譯文件方法二:javac –d . SC.java
系統(tǒng)行動在當(dāng)前文件夾(.)下新建p1文件夾,且將SC.class自制到p1文件夾下
6.2 接口
與C++語言不同,Java語言不支持多重繼承,為了實(shí)現(xiàn)多重繼承的功能,Java提供接口來實(shí)現(xiàn),且比多重繼承具有更強(qiáng)的功能。
多重繼承指一個類可以是多個類的子類
接口可以看作是沒有實(shí)現(xiàn)的方法和常量的集合。接口與抽象類相似,接口中的方法只是做了聲明,而沒有定義任何具體的操作方法。
接口功能:
?。?)通過接口可以實(shí)現(xiàn)不相關(guān)類的相同行為,而不需要考慮這些類之間的層次關(guān)系
(2)通過接口可以指明多個類需要實(shí)現(xiàn)的方法
?。?)通過接口可以了解對象的交互界面,而不需了解對象所對應(yīng)的類。
6.2.1 實(shí)現(xiàn)系統(tǒng)提供的接口
接口中定義的變量全部隱含為了final和static,表明這些變量不能被實(shí)現(xiàn)接口方法的類改變,這些變量還必須設(shè)置初值。如果接口為public,則接口中的方法和變量也全部為public,否則只能被處于同一包中的成員訪問。
類引用接口不叫繼承而稱為實(shí)現(xiàn)。
系統(tǒng)接口,如MouseListener和MouseMotionListener接口,定義了處理鼠標(biāo)事件的方法。
格式: class <類名> implements <接口名>[,<接口名>]
例:P110
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class SC extends Applet implements MouseListener , MouseMotionListener{
int x1,y1,x2,y2;
public void init( )
{ addMouseListener(this);
addMouseMotionListener(this); }
public void paint(Graphics g){
g.drawLine(x1,y1,x2,y2); // 書上在這錯
}
public void mousePressed(MouseEvent e){ //習(xí)慣寫成e,換成別的字符也行
x1=e.getX();
y1=e.getY(); }
public void mouseClicked(MouseEvent e){ }
public void mouseEntered(MouseEvent e){ }
public void mouseExited(MouseEvent e){ }
public void mouseReleased(MouseEvent e){ }
public void mouseDragged(MouseEvent e){
x2=e.getX();
y2=e.getY();
repaint(); }
public void mouseMoved(MouseEvent e){ }
}
說明:在實(shí)現(xiàn)接口時,要實(shí)現(xiàn)所有接口中定義的所有方法,方法的實(shí)現(xiàn)要以具有具體的實(shí)現(xiàn)內(nèi)容,也可以是空的方法,即只有方法名或參數(shù),沒有變量、沒有具體操作語句
6.2.2 創(chuàng)建自定義接口
格式:[修飾符] <interface> <接口名>
{ 靜態(tài)常量及方法聲明 }
說明:(1)Java系統(tǒng)會自動把接口中聲明的變量當(dāng)作static final類型,不管是否使用了這些修飾符,且必須賦初值,這些變量值都不能被修改。
?。?)接口中的方法默認(rèn)為abstract,不管有沒有這些修飾符。
?。?)接口若是public,那么該接口可被任意類實(shí)現(xiàn),否則只有與接口在同一個包中類的實(shí)現(xiàn)。
?。?)接口若為public,則接口中的變量也是public。
例:interface Colle{
int Max_Num=100;
void add(Object obj);
void delete(Object obj);
Object find(Object obj);
int currentCount( ); }
}
例:見P112
6.2.3 接口的繼承關(guān)系(自學(xué))
1.接口的單繼承
接口之間的繼承與類的繼承一樣使用extends
格式: interface <新接口名> extends <已有接口名>
例:見P113
如果一個類實(shí)現(xiàn)了接口B,那么它必須實(shí)現(xiàn)接口A和接口B中的全部方法。
2.接口的多重繼承
在Java語言中,不支持類的多重繼承,但支持接口的多重繼承
格式: interface <新接口名> extends <已有接口名1>[<,接口名2>…]
注意:引用接口時,必須實(shí)現(xiàn)接口中的所有方法。
6.3 異常處理
錯誤分編譯錯誤和運(yùn)行錯誤。編譯錯誤主要是程序中的語法錯誤,可以在程序編譯過程中發(fā)現(xiàn)。而而運(yùn)行錯誤就復(fù)雜得多,有些只在程序運(yùn)行過程中才會暴露出來。
Java語言的錯誤處理機(jī)制—異常處理,可以監(jiān)視某段代碼是否有錯,并且將各種錯誤集中處理。
以往需要由程序員完成的程序出錯情況判別,在Java中改為由系統(tǒng)承擔(dān)
6.3.1 什么是錯誤與異常
運(yùn)行錯誤分致命錯誤和異常兩種類型
1.致命性錯誤
如死循環(huán)或內(nèi)存溢出,運(yùn)行時程序本身無法解決,只能依靠其他程序干預(yù),否則會一直處于不正常狀態(tài)。
2.異常
如除數(shù)為0,操作數(shù)超出數(shù)據(jù)范圍,打開文件不存在等
6.3.2 異常發(fā)生的原因
?。?)Java虛擬機(jī)檢測到了非正常的執(zhí)行狀態(tài),這些狀態(tài)可能是由以下幾種情況引起的:
* 表達(dá)式的計(jì)算違反了Java語言的語義,例如整數(shù)除數(shù)為0
* 在載入或鏈接Java程序時出錯
* 超出了某些資源限制,例如使用了太多的內(nèi)存
這些異常都是無法預(yù)知的。
?。?)Java程序代碼中的throw語句被執(zhí)行
?。?)異步異常發(fā)生:
* Thread的stop方法被調(diào)用
* Java虛擬機(jī)內(nèi)部錯誤發(fā)生
6.3.3 異常處理機(jī)制
1.拋出異常
當(dāng)發(fā)生異常時將會拋出(throw)異常,即產(chǎn)生一個異常事件,生成一個異常對象,并把它提交給運(yùn)行系統(tǒng),再由系統(tǒng)找相應(yīng)的代碼來處理異常。一個異常對象可以由Java虛擬機(jī)產(chǎn)生,也可以由運(yùn)行的方法生成。異常對象中包含了異常事件類型、程序運(yùn)行狀態(tài)等必要信息。
2.捕獲異常
異常拋出后,運(yùn)行時系統(tǒng)從生成異常對象的代碼開始,沒方法的調(diào)用棧進(jìn)行查找,直到找到包含相應(yīng)處理的方法代碼,并把異常對象交給該方法為止,這個過程稱為捕獲(catch)異常。
簡單說異常處理機(jī)制:當(dāng)語義限制被違反時,將會拋出異常對象,并將引導(dǎo)程序流程從異常發(fā)生點(diǎn)轉(zhuǎn)移到程序員指定的處理異常方法代碼處進(jìn)行異常處理。
6.3.4 異常對象類型(補(bǔ))
異常類都是Throwable的子類,一般說程序不捕獲也不拋出類Error的對象(包括動態(tài)鏈接失敗、虛擬機(jī)錯誤等),而只處理Exception類的各子類對象
java.lang.Object-->java.lang.Throwable-->java.lang.Error
-->java.lang.Exception
-->java.lang.RuntimeException
-->java.lang.IOException
參見P116
6.3.5 異常的處理
格式: try {……} // 被監(jiān)視的代碼段
catch(異常類型1 e) // 要處理的第一種異常
catch(異常類型2 e) // 可以不寫成e
…………
finally {……} //最終處理
對異常進(jìn)行處理時,一般是把可能會發(fā)生異常情況的代碼放在try語句段中,利用try語句對這組代碼進(jìn)行監(jiān)視。發(fā)果發(fā)生了第一種異常,使用第一個catch中的代碼段處理;如果發(fā)生了第二種異常,則使用第二個catch代碼段處理。
如果希望在異常發(fā)生時能確保有一段代碼被執(zhí)行,那么應(yīng)該使用finally子句。
catch語句在執(zhí)行前,必須識別拋出的異常對象類型是catch能夠捕獲的“異常類”如果catch語句參數(shù)中聲明的異常類與拋出的異常類相同,或者是它的父類,catch語句就可以捕獲任何這種異常類的對象。e為相應(yīng)的異常對象。
例6.5 :見P115
如果不能確定會發(fā)生哪種情況的異常,那么最好指定catch的參數(shù)為Exception,即說明異常的類型為Exception。
例6.6 :見P116
捕獲例外的順序是和不同catch語句的順序相關(guān)的,因此在安排catch語句順序時,首先應(yīng)該捕獲最特殊的例外,然后再逐漸一般化,如果一個異常類和其子類都出現(xiàn)在catch子句中,應(yīng)把子類放在前面,否則將永遠(yuǎn)不會到達(dá)子類。另如果catch語句所捕獲的例外類型不是一個“終極”類型(即它還有子類),則一個catch語句可以同時捕獲多種例外。
例:P117
例:public class SC{
int count =1;
public static void main(String args[])
{SC abc=new SC();}
public SC( ){
while(true){
try{ int x=6/(count--);
System.out.println("in try,no exception") ; }
catch(ArithmeticException e)
{ System.out.println("in catch,divided by zero");}
finally{
System.out.println("in finally");
if (count==-1) break; }
} System.out.println("end of program"); } }
運(yùn)行結(jié)果:in try,no exception
in finally
in catch,divided by zero
in finally
end of program
6.3.6 throw語句
異常對象可以是Java系統(tǒng)拋出的。也可以通過代碼實(shí)現(xiàn),使用throw語句就可以明確拋出一個異常。
格式:throw <異常對象>
如:IOException e new IOException( ) ;
throw e;
例:P118
6.3.7 throws子句
throws用來表明一個方法可能拋出的各種異常,并說明該方法會拋出但不捕獲異常。
1.拋出異常的方法(自學(xué))
2.調(diào)用方法處理異常(自學(xué))
3.由方法拋出異常交系統(tǒng)處理
對于程序中需要處理的異常,一般編寫try-catch-finally語句捕獲處理,而對于程序中無法處理必須由系統(tǒng)處理的異常,可以使用throws語句在方法中拋出異常交由系統(tǒng)處理。
格式:返回類型 方法名(參數(shù)表) throws 異常類型表
例:P123
例:public int read( ) throws IOException{……}
說明:(1)該方法將不對這些例外進(jìn)行處理,而是聲明拋棄它們。
?。?)對于非運(yùn)行時例外,如前IOException等,程序中必須要作出處理,或者捕獲,或聲明拋棄。而對于運(yùn)行時例外,如ArithmeticException, IndexOutOfBoundsException,則可以不做處理。
6.3.8 finally語句
每個try語句至少要有一個與之相匹配的catch或finally子句。
例:P121
finally子句總是在方法返回前執(zhí)行
6.3.9 編譯時對異常情況的檢查
1.可檢測的異常
在編譯時,編譯器將分析哪些方法會產(chǎn)生可檢測的異常,然后檢查方法中的可檢測異常的處理部分。如果方法中沒有異常處理部分,就要在方法的throws子句說明該方法會拋出但不捕獲的異常,以告知調(diào)用它的其他方法,即將異常上交給調(diào)用者處理。
如果程序在運(yùn)行的過程中拋出異常,而這個異常是可檢測的,則在程序中必須捕獲這個異常進(jìn)行處理或聲明拋棄(throws)該異常,捕獲異常可以使用try語句,而拋棄異常在方法聲明時聲明,即在方法聲明后加上throws xxxException子句,拋棄外個異常時可在各異常間使用“,”分隔。
例P123:
import java.io.*;
public class SC{
public static void main(String a[]) throws IOException {
//省略throws IOException 編譯時即報錯
FileInputStream fis=new FileInputStream("a2.txt"); }}
2.不可檢測的異常(運(yùn)行時異常類)
不可檢測的異常類是RuntimeException及其子類、Error及其子類,其他異常類則是可檢測的類。編譯器對不可檢測的異常類不進(jìn)行檢查。
解釋器在執(zhí)行程序時會對出現(xiàn)異常的程序給出異常報告。
6.3.10 創(chuàng)建自己的異常類(自學(xué))
格式:<class> <自定義異常名> <extends> < Exception>{……}
在使用各種例外類型時,建議:
?。?)對于運(yùn)行時例外,如果不能預(yù)測它何時發(fā)生,程序可以不做處理,而是讓虛擬機(jī)處理它。
(2)如果程序可以預(yù)知運(yùn)行時例外可以發(fā)生的地點(diǎn)和時間,則應(yīng)該在程序中進(jìn)行處理,而不應(yīng)簡單地把它交給運(yùn)行時系統(tǒng)。
(3)在自定義例外類時,如果它所對應(yīng)的異常事件通??偸窃谶\(yùn)行時產(chǎn)生的,而且不容易預(yù)測它將在何時、何處發(fā)生,則可以把它定義為運(yùn)行時例外,否則應(yīng)定義為非運(yùn)行時例外。
使用異常處理準(zhǔn)則:
(1)盡可能在當(dāng)前程序中解決問題,否則應(yīng)將異常向更外層的程序拋出。
(2)簡化編碼,不要因加入異常處理而使程序變得復(fù)雜難懂。