




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、【java編程】java中異步socket類的實現(xiàn)和源代碼- - java中異步socket類的實現(xiàn)和源代碼作者: HYPERLINK dozb我們知道,java中socket類一般操作都是同步進行,常常在read的時候socket就會阻塞直到有數(shù)據(jù)可讀或socket連接斷開的時候才返回,雖然可以設(shè)置超時返回,但是這樣比較低效,需要做一個循環(huán)來不停掃描數(shù)據(jù)是否可讀??磥?,在同一個線程中,要是想實現(xiàn)異步讀寫不太容易。下面介紹的這個類實現(xiàn)了偽異步socket通訊?;舅枷刖褪窃诂F(xiàn)有socket類的基礎(chǔ)上進行封裝,當socket連接建立成功后,立即創(chuàng)建一個socket數(shù)據(jù)接收線程,專門負責阻塞式的s
2、ocket讀取(read),而當前線程負責數(shù)據(jù)的發(fā)送(send)。另外定義了一個接口,包括了socket的各種事件的回調(diào)。我們要實現(xiàn)這個接口,在接口實現(xiàn)類中創(chuàng)建異步socket對象,并且傳遞接口類到異步socket對象中,目的是有socket事件的時候回調(diào)我們的方法。下面是接口:SocketExHandler.java package ;import .*; /* * Title: * Description: * Copyright: Copyright (c) 2001 * Company: * author dozb * version 1.0 */* * 異步Socket Client
3、 Interface * 使用方法: * 1.定義類 MySocketClientEx 實現(xiàn)SocketExHandler接口,實現(xiàn) OnReceive OnClose OnConnect 事件 * 2.在類中實現(xiàn)start方法 MySocketEx = new SocketEx(this,ip,port) * 3.在類中實現(xiàn)stop方法 delete MySocketEx * 4.當有數(shù)據(jù)到達時會觸發(fā)OnReceive事件 * 5.當對方SOCKET關(guān)閉時會觸發(fā)OnClose事件 * 6.當SOCKET建立時會觸發(fā)OnConnect事件 */* * 異步Socket Server Inter
4、face * 使用方法: * 1.定義類 MySocketServerEx 實現(xiàn)SocketExHandler接口,實現(xiàn) OnReceive OnListen OnClose OnAccept 事件 * 2.在類中實現(xiàn)start方法 MySocketEx = new ServerSocketEx(this,ip,port) * 3.在類中實現(xiàn)stop方法 delete MySocketEx * 4.當開始監(jiān)聽時會觸發(fā)OnListen事件 * 5.當SOCKET關(guān)閉時會觸發(fā)OnClose事件 * 6.當有客戶端SOCKET要建立連接時會觸發(fā)OnAccept事件 */public interfac
5、e SocketExHandler/當客戶端sock數(shù)據(jù)到達時觸發(fā)public void OnReceive(Object socket,byte buf,int nLen);/當客戶端sock連接建立成功時觸發(fā)public void OnConnect(Object socket);/當服務(wù)端sock監(jiān)聽開始時觸發(fā)public void OnListen(Object socket);/當服務(wù)端sock接受一個新的sock連接時觸發(fā)public void OnAccept(Object socket,SocketEx ClientSocket) ;/當sock關(guān)閉時觸發(fā)public void
6、 OnClose(Object socket); 下面是異步客戶端socket類: SocketEx.java package ;import java.io.*;import .*;import java.util.*;import .SocketExHandler;/* * Title: * Description: * Copyright: Copyright (c) 2001 * Company: * author dozb * version 1.0 */public class SocketEx implements Runnablepublic static final bool
7、ean isdebug = true;/調(diào)試/* *構(gòu)造函數(shù). */public SocketEx(SocketExHandler seh,Socket ClientSocket)this.seh = seh;thisSocket = ClientSocket;InitNotify();public SocketEx(SocketExHandler seh,String host,int port) throws IOException this.seh = seh;thisSocket = new Socket(host,port);InitNotify();public SocketEx(
8、SocketExHandler seh, InetAddress address, int port ) throws IOException this.seh = seh;thisSocket = new Socket(address, port);InitNotify();public SocketEx(SocketExHandler seh, String host, int port, InetAddress localAddr, int localPort ) throws IOException this.seh = seh;thisSocket = new Socket(host
9、,port,localAddr,localPort );InitNotify();public SocketEx(SocketExHandler seh, InetAddress address, int port, InetAddress localAddr, int localPort ) throws IOException this.seh = seh;thisSocket = new Socket(address, port, localAddr,localPort );InitNotify();/* * 實現(xiàn)Socket的可見方法. */public synchronized vo
10、id close() throws IOExceptionIsRunning = false;thisSocket.close();public InetAddress getInetAddress() return thisSocket.getInetAddress();public InputStream getInputStream() throws IOExceptionreturn thisSocket.getInputStream(); public InetAddress getLocalAddress() return thisSocket.getLocalAddress()
11、; public int getLocalPort() return thisSocket.getLocalPort() ; public OutputStream getOutputStream() throws IOExceptionreturn thisSocket.getOutputStream(); public int getPort() return thisSocket.getPort() ; public int getSoLinger() throws SocketExceptionreturn thisSocket.getSoLinger(); public synchr
12、onized int getSoTimeout() throws SocketException return thisSocket.getSoTimeout(); public boolean getTcpNoDelay() throws SocketException return thisSocket.getTcpNoDelay(); public void setSoLinger( boolean on, int val ) throws SocketException thisSocket.setSoLinger(on,val); public synchronized void s
13、etSoTimeout( int timeout ) throws SocketException thisSocket.setSoTimeout( timeout ) ; public void setTcpNoDelay( boolean on ) throws SocketException thisSocket.setTcpNoDelay(on); public String toString() return thisSocket.toString() ; /* * 獲取Socket */public Socket GetSocket()return thisSocket;/* *
14、初始化異步Socket */private void ShowMsg(String Msg)if(isdebug)System.out.println(Msg);private void InitNotify()if(NotifyThread != null) return ;trybiStream = new BufferedInputStream(getInputStream();thisSocket.setSoTimeout(0); catch(IOException e)ShowMsg(InitNotify() IOException.);IsRunning = true;Notify
15、Thread = new Thread(this,SocketEx_NoitfyThread);NotifyThread.setDaemon(true);NotifyThread.start();if(seh !=null)seh.OnConnect(this);/* * 關(guān)閉Socket */private void Close()tryclose();catch(Exception eclose)ShowMsg(Close() Exception.);protected void finalize() throws ThrowableClose();super.finalize();/*
16、* Thread 運行 */public void run()while(IsRunning)tryif(getInputStream().read(buf,0,1) = 0)/試讀一個字節(jié)DoClose();return ;if(!DoReceive(getInputStream().available()return ;catch(Exception e)ShowMsg(run() Exception.);DoClose();return ;tryThread.sleep(0); /catch(InterruptedException e)ShowMsg(run() Interrupted
17、Exception.);DoClose();return ;/* * 當有數(shù)據(jù)到達時的回調(diào)方法. */private boolean DoReceive(int nCanReadCount)tryint len = 0,nCurrReadCount=0,nStart=1;dofor(int i=nStart;i(BUFLEN-2)nCurrReadCount = BUFLEN-2;elsenCurrReadCount = nCanReadCount;len = biStream.read(buf,nStart,nCurrReadCount);if(len = 0)DoClose();retur
18、n false;nCanReadCount -= len;buflen+nStart = 0;if(seh !=null)seh.OnReceive(this,buf,len+nStart);nStart = 0;while(nCanReadCount 0); catch(Exception excpt)ShowMsg(DoReceive() Exception.);DoClose();return false; return true;/* * 當Socket建立連接時的回調(diào)方法. */private void DoConnect()if(seh !=null)seh.OnConnect(t
19、his);/* * 當Socket關(guān)閉時的回調(diào)方法. */private void DoClose()try if(IsRunning) Close(); if(seh !=null) seh.OnClose(this); IsRunning = false; catch(Exception e)ShowMsg(DoClose() Exception.);/* * 以下實現(xiàn)不要改動! */private Thread NotifyThread=null;private boolean IsRunning = false;private Socket thisSocket = null;priv
20、ate static final int BUFLEN = 4097;privatebyte buf = new byteBUFLEN;privateBufferedInputStream biStream = null;privateSocketExHandler seh=null; 下面是異步socketserver類: ServerSocketEx .java package ;import java.io.*;import .*; import java.util.*; /* * Title: * Description: * Copyright: Copyright (c) 2001
21、 * Company: * author dozb * version 1.0 */public class ServerSocketEx extends ServerSocket implements Runnable/* * 以下實現(xiàn)不要改動! */public ServerSocketEx(SocketExHandler seh, int port ) throws IOException super(port);this.seh = seh;Listen();public ServerSocketEx(SocketExHandler seh, int port, int backlog
22、 ) throws IOException super(port,backlog);this.seh = seh;Listen();public ServerSocketEx(SocketExHandler seh, int port, int backlog, InetAddress bindAddr ) throws IOException super(port,backlog, bindAddr);this.seh = seh;Listen();public void setTimeout(int timeout) this.timeout = timeout; public stati
23、c Vector GetClientPool()return ClientPool;public static void CloseAllClients()for(int i=0;i= 0) try sleeping = true; sleep(sleepTime); sleeping = false; catch (InterruptedException i) /Diagnostic.out.println(TIMER: Caught me napping); /* * Add a new task */ public void add(TimerClient client, int ev
24、entId, long delay, boolean repeat) TimerTask t = new TimerTask(client, eventId, delay, repeat); synchronized (tasks) tasks.addElement(Object)t); / Want instant response - wake the thread if its napping / unfortunately the interrupt() method is not working/ if (sleeping)/ interrupt(); if (suspended)
25、synchronized(this) notify(); /Diagnostic.out.println(TIMER: Resume); suspended = false; /* * Find the job and mark it for deletion */ public void end(TimerClient client, int eventId) synchronized (tasks) for (int i = 0; i tasks.size(); i+) TimerTask t = (TimerTask)tasks.elementAt(i); /if (!t.deleteP
26、ending & t.client = client & t.eventId = eventId) if (t.deletePending = false & t.client = client & t.eventId = eventId) / JPBS - if we dont reset repeat, deletePending will be set again t.repeat = false; t.deletePending = true; break; /* * Clear out all the dead wood */ void purge() for (int i = 0;
27、 i tasks.size(); i+) TimerTask t = (TimerTask)tasks.elementAt(i); if (t.deletePending) /Diagnostic.out.println(TIMER: purged); tasks.removeElementAt(i); i-; long scan() / The value added to the current time determines the MAX time until / the next scan / This is 100 now since errupt() is not impleme
28、nted long nextTime = System.currentTimeMillis() + 100; for (int i = 0; i = timeNext) /Diagnostic.out.println(TIMER: fire); / Fire the event client.timerEvent(eventId); / Update the next time timeNext = System.currentTimeMillis() + timeDelay; deletePending = !repeat; 下面是使用上面的異步socket類,做的demo開發(fā) DemoAp
29、pSocketHandler.java package ;import .*; import java.util.*;/* * Title: * Description: * Copyright: Copyright (c) 2001 * Company: * author dozb * version 1.0 */public interface DemoAppSocketHandler/當客戶端sock有數(shù)據(jù)到達時觸發(fā)public void OnProcessCmd(Object socket,String FromArea,String ToArea,String ChannNo,Str
30、ing MainFun,String SubFun,Vector ParamList);/當客戶端sock連接建立成功時觸發(fā)public void OnConnect(Object socket);/當服務(wù)端sock監(jiān)聽開始時觸發(fā)public void OnListen(Object socket);/當服務(wù)端sock接受一個新的sock連接時觸發(fā)public void OnAccept(Object socket,SocketEx ClientSocket) ;/當sock關(guān)閉時觸發(fā)public void OnClose(Object socket);DemoAppSocket.java p
31、ackage ;import java.io.*;import java.util.*;import com.ly.util.*;/* * Title: * Description: * Copyright: Copyright (c) 2001 * Company: * author dozb * version 1.0 */這個類是異步socket 客戶端和服務(wù)端的使用演示/對于客戶端,實現(xiàn)了斷開后自動連接/這個類是SocketExHandler 和 TimerClient 接口的實現(xiàn)public class DemoAppSocket implements SocketExHandler
32、,TimerClient/Sock構(gòu)造函數(shù)public DemoAppSocket(DemoAppSocketHandler issh,boolean isServer,String ip,int port) this.issh = issh;this.isServer = isServer;this.ip = ip;if(this.ip = null) this.ip = ;this.port = port;if(this.port 0) this.port = 0; /調(diào)用完構(gòu)造后調(diào)用這個函數(shù)創(chuàng)建sock對象public void create() if(!start() TimerCtl
33、.startTimer(this,eventId,30*1000,true); /這個方法一般不需要直接調(diào)用 public boolean start() if(this.isServer) return startServer(); else return startClient(); /停止socket public void stop() TimerCtl.stopTimer(this,eventId);if(this.isServer) stopServer(); else stopClient(); /發(fā)送socket消息 public boolean SendCmd(Object
34、socket,String strCmd) SocketEx currSocketEx = (SocketEx)socket;if(!isServer & currSocketEx=null) currSocketEx = socketEx; if(currSocketEx = null) return false; try PrintWriter Sender = new PrintWriter(currSocketEx.getOutputStream(),true); Sender.print(strCmd); Sender.flush(); return true; catch(Exce
35、ption e) return false; /發(fā)送socket消息 public boolean SendCmd(Object socket,String FromArea,String ToArea,String ChannNo,String MainFun,String SubFun,String Param) String strCmd = FromArea + ToArea + ChannNo + MainFun+SubFun+&+Param+&;return SendCmd(socket,strCmd); /獲得IP地址 public String getIp() return i
36、p; /獲得端口號 public int getPort() return port; protected boolean startClient() if(socketEx != null) try socketEx.close(); catch(IOException e); socketEx = null; try socketEx = new SocketEx(this,ip,port); TimerCtl.stopTimer(this,eventId); return true; catch(IOException e) socketEx = null; return false;p
37、rotected boolean startServer() if(serverSocketEx != null) try serverSocketEx.close(); catch(IOException e); serverSocketEx = null; try serverSocketEx = new ServerSocketEx(this,port); TimerCtl.stopTimer(this,eventId); return true; catch(IOException e) serverSocketEx = null; return false;protected voi
38、d stopServer() if(serverSocketEx != null) try serverSocketEx.close(); catch(IOException e); serverSocketEx = null; protected void stopClient() if(socketEx != null) try socketEx.close(); catch(IOException e); socketEx = null; public void timerEvent(int id) start(); static public String DealStr(String
39、 strS) int CMDHEAD_LEN = 22; String ret = new String2;/0留下的字符串1完整的CMDret0=strS;/假如只有一個&或沒有&則不完整 int FirstPos=strS.indexOf(&); if(FirstPos=-1) return ret; if(FirstPos != CMDHEAD_LEN-1) strS = strS.substring(FirstPos+1); return DealStr(strS); int nSecondPos = strS.indexOf(&,FirstPos+1); if(nSecondPos0
40、) return ret; /可能格式不正確了 if(strS.length() CMDHEAD_LEN) return ret; ret1 = strS.substring(0,nSecondPos+1); ret0=strS.substring(nSecondPos+1); return ret; public void OnReceive(Object socket,byte buf,int nLen) String ReceiveBuff = sReceiveBuf + (new String(buf,0,nLen);do/分解成單個的命令串String strCmd = DealSt
41、r(ReceiveBuff);ReceiveBuff = strCmd0;if(strCmd1=null | strCmd1.equals() break;System.out.println(strCmd1);String FromArea=strCmd1.substring(0,6);String ToArea=strCmd1.substring(6,12);String ChannNo=strCmd1.substring(12,15);String MainFun=strCmd1.substring(15,18);String SubFun=strCmd1.substring(18,21
42、);String Param =strCmd1.substring(22,strCmd1.length()-1);Vector ParamList=new Vector();int nLastPos=0;while(true)int nPos = Param.indexOf(,nLastPos);if(nPos 0)ParamList.add(Param.substring(nLastPos);/System.out.println(Param.substring(nLastPos);break;String sParam = Param.substring(nLastPos,nPos);Pa
43、ramList.add(sParam);/System.out.println(sParam);nLastPos = nPos+1;DoProcessCmd(socket,FromArea,ToArea,ChannNo,MainFun,SubFun,ParamList);while(true);sReceiveBuf = ReceiveBuff;if(sReceiveBuf = null) sReceiveBuf=null; protected void DoProcessCmd(Object socket,String FromArea,String ToArea,String ChannN
44、o,String MainFun,String SubFun,Vector ParamList) if(issh !=null)issh.OnProcessCmd(socket,FromArea,ToArea,ChannNo,MainFun, SubFun, ParamList); public void OnConnect(Object socket) if(issh !=null) issh.OnConnect(socket);public void OnListen(Object socket) if(issh !=null) issh.OnListen(socket);public v
45、oid OnAccept(Object socket,SocketEx ClientSocket) if(issh !=null) issh.OnAccept(socket,ClientSocket);public void OnClose(Object socket)notifyAll(); TimerCtl.startTimer(this,eventId,30*1000,true);if(issh !=null) issh.OnClose(socket); /Socket SocketEx socketEx = null;ServerSocketEx serverSocketEx=null
46、; final int eventId = 1; String sReceiveBuf=;DemoAppSocketHandler issh=null;boolean isServer=false;String ip=;int port=20000;通過這種方式,可以高效地使用socket通訊,在異步socket版本沒有發(fā)布以前,不失是一種解決問題的方法。:)附錄資料:如何處理Java異常及常見異常六種異常處理的陋習(xí)你覺得自己是一個Java專家嗎?是否肯定自己已經(jīng)全面掌握了Java的異常處理機制?在下面這段代碼中,你能夠迅速找出異常處理的六個問題嗎? 1 OutputStreamWriter
47、out = . 2 java.sql.Connection conn = . 3 try / 4 Statement stat = conn.createStatement(); 5 ResultSet rs = stat.executeQuery( 6 select uid, name from user); 7 while (rs.next() 8 9 out.println(ID: + rs.getString(uid) / 10 ,姓名: + rs.getString(name); 11 12 conn.close(); / 13 out.close(); 14 15 catch(Ex
48、ception ex) / 16 17 ex.printStackTrace(); /, 18 作為一個Java程序員,你至少應(yīng)該能夠找出兩個問題。但是,如果你不能找出全部六個問題,請繼續(xù)閱讀本文。 本文討論的不是Java異常處理的一般性原則,因為這些原則已經(jīng)被大多數(shù)人熟知。我們要做的是分析各種可稱為“反例”(anti-pattern)的違背優(yōu)秀編碼規(guī)范的常見壞習(xí)慣,幫助讀者熟悉這些典型的反面例子,從而能夠在實際工作中敏銳地察覺和避免這些問題。 反例之一:丟棄異常 代碼:15行-18行。 這段代碼捕獲了異常卻不作任何處理,可以算得上Java編程中的殺手。從問題出現(xiàn)的頻繁程度和禍害程度來看,它也
49、許可以和C/C+程序的一個惡名遠播的問題相提并論?不檢查緩沖區(qū)是否已滿。如果你看到了這種丟棄(而不是拋出)異常的情況,可以百分之九十九地肯定代碼存在問題(在極少數(shù)情況下,這段代碼有存在的理由,但最好加上完整的注釋,以免引起別人誤解)。 這段代碼的錯誤在于,異常(幾乎)總是意味著某些事情不對勁了,或者說至少發(fā)生了某些不尋常的事情,我們不應(yīng)該對程序發(fā)出的求救信號保持沉默和無動于衷。調(diào)用一下printStackTrace算不上“處理異?!?。不錯,調(diào)用printStackTrace對調(diào)試程序有幫助,但程序調(diào)試階段結(jié)束之后, printStackTrace就不應(yīng)再在異常處理模塊中擔負主要責任了。 丟棄異
50、常的情形非常普遍。打開JDK的ThreadDeath類的文檔,可以看到下面這段說明:“特別地,雖然出現(xiàn)ThreadDeath是一種正常的情形,但ThreadDeath類是Error而不是Exception的子類,因為許多應(yīng)用會捕獲所有的Exception然后丟棄它不再理睬?!边@段話的意思是,雖然ThreadDeath代表的是一種普通的問題,但鑒于許多應(yīng)用會試圖捕獲所有異常然后不予以適當?shù)奶幚?,所以JDK把 ThreadDeath定義成了Error的子類,因為Error類代表的是一般的應(yīng)用不應(yīng)該去捕獲的嚴重問題??梢?,丟棄異常這一壞習(xí)慣是如此常見,它甚至已經(jīng)影響到了Java本身的設(shè)計。 那么,應(yīng)
51、該怎樣改正呢?主要有四個選擇: 1、處理異常。針對該異常采取一些行動,例如修正問題、提醒某個人或進行其他一些處理,要根據(jù)具體的情形確定應(yīng)該采取的動作。再次說明,調(diào)用printStackTrace算不上已經(jīng)“處理好了異?!?。 2、重新拋出異常。處理異常的代碼在分析異常之后,認為自己不能處理它,重新拋出異常也不失為一種選擇。 3、把該異常轉(zhuǎn)換成另一種異常。大多數(shù)情況下,這是指把一個低級的異常轉(zhuǎn)換成應(yīng)用級的異常(其含義更容易被用戶了解的異常)。 4、不要捕獲異常。 結(jié)論一:既然捕獲了異常,就要對它進行適當?shù)奶幚?。不要捕獲異常之后又把它丟棄,不予理睬。 反例之二:不指定具體的異常 代碼:15行。 許多
52、時候人們會被這樣一種“美妙的”想法吸引:用一個catch語句捕獲所有的異常。最常見的情形就是使用catch(Exception ex)語句。但實際上,在絕大多數(shù)情況下,這種做法不值得提倡。為什么呢? 要理解其原因,我們必須回顧一下catch語句的用途。catch語句表示我們預(yù)期會出現(xiàn)某種異常,而且希望能夠處理該異常。異常類的作用就是告訴 Java編譯器我們想要處理的是哪一種異常。由于絕大多數(shù)異常都直接或間接從java.lang.Exception派生,catch (Exception ex)就相當于說我們想要處理幾乎所有的異常。 再來看看前面的代碼例子。我們真正想要捕獲的異常是什么呢?最明顯的
53、一個是SQLException,這是JDBC操作中常見的異常。另一個可能的異常是IOException,因為它要操作OutputStreamWriter。顯然,在同一個catch塊中處理這兩種截然不同的異常是不合適的。如果用兩個catch塊分別捕獲SQLException和IOException就要好多了。這就是說,catch語句應(yīng)當盡量指定具體的異常類型,而不應(yīng)該指定涵蓋范圍太廣的Exception類。 另一方面,除了這兩個特定的異常,還有其他許多異常也可能出現(xiàn)。例如,如果由于某種原因,executeQuery返回了null,該怎么辦?答案是讓它們繼續(xù)拋出,即不必捕獲也不必處理。實際上,我們
54、不能也不應(yīng)該去捕獲可能出現(xiàn)的所有異常,程序的其他地方還有捕獲異常的機會?直至最后由JVM處理。 結(jié)論二:在catch語句中盡可能指定具體的異常類型,必要時使用多個catch。不要試圖處理所有可能出現(xiàn)的異常。 反例之三:占用資源不釋放 代碼:3行-14行。 異常改變了程序正常的執(zhí)行流程。這個道理雖然簡單,卻常常被人們忽視。如果程序用到了文件、Socket、JDBC連接之類的資源,即使遇到了異常,也要正確釋放占用的資源。為此,Java提供了一個簡化這類操作的關(guān)鍵詞finally。 finally是樣好東西:不管是否出現(xiàn)了異常,F(xiàn)inally保證在try/catch/finally塊結(jié)束之前,執(zhí)行清
55、理任務(wù)的代碼總是有機會執(zhí)行。遺憾的是有些人卻不習(xí)慣使用finally。 當然,編寫finally塊應(yīng)當多加小心,特別是要注意在finally塊之內(nèi)拋出的異常?這是執(zhí)行清理任務(wù)的最后機會,盡量不要再有難以處理的錯誤。 結(jié)論三:保證所有資源都被正確釋放。充分運用finally關(guān)鍵詞。反例之四:不說明異常的詳細信息 代碼:3行-18行。 仔細觀察這段代碼:如果循環(huán)內(nèi)部出現(xiàn)了異常,會發(fā)生什么事情?我們可以得到足夠的信息判斷循環(huán)內(nèi)部出錯的原因嗎?不能。我們只能知道當前正在處理的類發(fā)生了某種錯誤,但卻不能獲得任何信息判斷導(dǎo)致當前錯誤的原因。 printStackTrace的堆棧跟蹤功能顯示出程序運行到當前
56、類的執(zhí)行流程,但只提供了一些最基本的信息,未能說明實際導(dǎo)致錯誤的原因,同時也不易解讀。 因此,在出現(xiàn)異常時,最好能夠提供一些文字信息,例如當前正在執(zhí)行的類、方法和其他狀態(tài)信息,包括以一種更適合閱讀的方式整理和組織printStackTrace提供的信息。 結(jié)論四:在異常處理模塊中提供適量的錯誤原因信息,組織錯誤信息使其易于理解和閱讀。 反例之五:過于龐大的try塊 代碼:3行-14行。 經(jīng)??梢钥吹接腥税汛罅康拇a放入單個try塊,實際上這不是好習(xí)慣。這種現(xiàn)象之所以常見,原因就在于有些人圖省事,不愿花時間分析一大塊代碼中哪幾行代碼會拋出異常、異常的具體類型是什么。把大量的語句裝入單個巨大的tr
57、y塊就象是出門旅游時把所有日常用品塞入一個大箱子,雖然東西是帶上了,但要找出來可不容易。 一些新手常常把大量的代碼放入單個try塊,然后再在catch語句中聲明Exception,而不是分離各個可能出現(xiàn)異常的段落并分別捕獲其異常。這種做法為分析程序拋出異常的原因帶來了困難,因為一大段代碼中有太多的地方可能拋出Exception。 結(jié)論五:盡量減小try塊的體積。 反例之六:輸出數(shù)據(jù)不完整 代碼:7行-11行。 不完整的數(shù)據(jù)是Java程序的隱形殺手。仔細觀察這段代碼,考慮一下如果循環(huán)的中間拋出了異常,會發(fā)生什么事情。循環(huán)的執(zhí)行當然是要被打斷的,其次, catch塊會執(zhí)行?就這些,再也沒有其他動作
58、了。已經(jīng)輸出的數(shù)據(jù)怎么辦?使用這些數(shù)據(jù)的人或設(shè)備將收到一份不完整的(因而也是錯誤的)數(shù)據(jù),卻得不到任何有關(guān)這份數(shù)據(jù)是否完整的提示。對于有些系統(tǒng)來說,數(shù)據(jù)不完整可能比系統(tǒng)停止運行帶來更大的損失。 較為理想的處置辦法是向輸出設(shè)備寫一些信息,聲明數(shù)據(jù)的不完整性;另一種可能有效的辦法是,先緩沖要輸出的數(shù)據(jù),準備好全部數(shù)據(jù)之后再一次性輸出。 結(jié)論六:全面考慮可能出現(xiàn)的異常以及這些異常對執(zhí)行流程的影響。 改寫后的代碼 根據(jù)上面的討論,下面給出改寫后的代碼。也許有人會說它稍微有點?嗦,但是它有了比較完備的異常處理機制。 OutputStreamWriter out = . java.sql.Connecti
59、on conn = . try Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery( select uid, name from user); while (rs.next() out.println(ID: + rs.getString(uid) + ,姓名: + rs.getString(name); catch(SQLException sqlex) out.println(警告:數(shù)據(jù)不完整); throw new ApplicationException(讀取數(shù)據(jù)時出現(xiàn)SQL錯誤, sqle
60、x); catch(IOException ioex) throw new ApplicationException(寫入數(shù)據(jù)時出現(xiàn)IO錯誤, ioex); finally if (conn != null) try conn.close(); catch(SQLException sqlex2) System.err(this.getClass().getName() + .mymethod - 不能關(guān)閉數(shù)據(jù)庫連接: + sqlex2.toString(); if (out != null) try out.close(); catch(IOException ioex2) System.e
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 入場人員檔案三級教育
- 浙江省寧波市慈溪市2023-2024學(xué)年四年級下學(xué)期數(shù)學(xué)期末測試試卷(含答案)
- 全國家居建材裝飾專業(yè)市場統(tǒng)計匯編159
- 培訓(xùn)學(xué)校老師管理制度
- 四川自貢汽配城項目投資可行性報告
- 山西省呂梁市2022-2023學(xué)年高二下學(xué)期期末考試化學(xué)試題(含答案)
- 初中英語七年級下冊統(tǒng)編教案 七下Unit6 Outdoor fun第7課時
- 倉儲調(diào)研活動方案
- 倉庫清倉積木活動方案
- 仙桃婦聯(lián)活動方案
- 消防宣傳月全民消防生命至上消防安全教育課件
- 24年追覓在線測評28題及答案
- 咨詢實施顧問能力素質(zhì)模型
- 2025年上海市數(shù)學(xué)高考一輪復(fù)習(xí):立體幾何(Ⅰ)(考點練+模擬練)含詳解
- 情侶協(xié)議書電子版簡單模板
- 建筑水電安裝工程規(guī)范要求中的水泵安裝要求
- 【usmile電動牙刷的營銷策略探析8600字(論文)】
- 小兒麻醉術(shù)后并發(fā)癥
- 2019青鳥消防JBF6481編碼器使用指南
- 2024-2030年中國生物基化學(xué)品行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略分析報告
- 《機械設(shè)計基礎(chǔ)》試題庫(主觀題及答案)
評論
0/150
提交評論