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