




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、俄羅斯方塊java源代碼提供 import java.awt.*; import java.awt.event.*; /俄羅斯方塊類 public class ERS_Block extends Frame public static boolean isPlay=false; public static int level=1,score=0; public static TextField scoreField,levelField; public static MyTimer timer; GameCanvas gameScr; public static void main(Strin
2、g argus) ERS_Block ers = new ERS_Block(俄羅斯方塊游戲 V1.0 Author:Vincent); WindowListener win_listener = new WinListener(); ers.addWindowListener(win_listener); /俄羅斯方塊類的構(gòu)造方法 ERS_Block(String title) super(title); setSize(600,480); setLayout(new GridLayout(1,2); gameScr = new GameCanvas(); gameScr.addKeyLis
3、tener(gameScr); timer = new MyTimer(gameScr); timer.setDaemon(true); timer.start(); timer.suspend(); add(gameScr); Panel rightScr = new Panel(); rightScr.setLayout(new GridLayout(2,1,0,30); rightScr.setSize(120,500); add(rightScr); /右邊信息窗體的布局 MyPanel infoScr = new MyPanel(); infoScr.setLayout(new Gr
4、idLayout(4,1,0,5); infoScr.setSize(120,300); rightScr.add(infoScr); /定義標(biāo)簽和初始值 Label scorep = new Label(分?jǐn)?shù):,Label.LEFT); Label levelp = new Label(級(jí)數(shù):,Label.LEFT); scoreField = new TextField(8); levelField = new TextField(8); scoreField.setEditable(false); levelField.setEditable(false); infoScr.add(sc
5、orep); infoScr.add(scoreField); infoScr.add(levelp); infoScr.add(levelField); scorep.setSize(new Dimension(20,60); scoreField.setSize(new Dimension(20,60); levelp.setSize(new Dimension(20,60); levelField.setSize(new Dimension(20,60); scoreField.setText(0); levelField.setText(1); /右邊控制按鈕窗體的布局 MyPanel
6、 controlScr = new MyPanel(); controlScr.setLayout(new GridLayout(5,1,0,5); rightScr.add(controlScr); /定義按鈕play Button play_b = new Button(開始游戲); play_b.setSize(new Dimension(50,200); play_b.addActionListener(new Command(Command.button_play,gameScr); /定義按鈕Level UP Button level_up_b = new Button(提高級(jí)數(shù))
7、; level_up_b.setSize(new Dimension(50,200); level_up_b.addActionListener(new Command(Command.button_levelup,gameScr); /定義按鈕Level Down Button level_down_b =new Button(降低級(jí)數(shù)); level_down_b.setSize(new Dimension(50,200); level_down_b.addActionListener(new Command(Command.button_leveldown,gameScr); /定義按鈕
8、Level Pause Button pause_b =new Button(游戲暫停); pause_b.setSize(new Dimension(50,200); pause_b.addActionListener(new Command(Command.button_pause,gameScr); /定義按鈕Quit Button quit_b = new Button(退出游戲); quit_b.setSize(new Dimension(50,200); quit_b.addActionListener(new Command(Command.button_quit,gameScr
9、); controlScr.add(play_b); controlScr.add(level_up_b); controlScr.add(level_down_b); controlScr.add(pause_b); controlScr.add(quit_b); setVisible(true); gameScr.requestFocus(); /重寫MyPanel類,使Panel的四周留空間 class MyPanel extends Panel public Insets getInsets() return new Insets(30,50,30,50); /游戲畫布類 class
10、GameCanvas extends Canvas implements KeyListener final int unitSize = 30; /小方塊邊長(zhǎng) int rowNum; /正方格的行數(shù) int columnNum; /正方格的列數(shù) int maxAllowRowNum; /允許有多少行未削 int blockInitRow; /新出現(xiàn)塊的起始行坐標(biāo) int blockInitCol; /新出現(xiàn)塊的起始列坐標(biāo) int scrArr; /屏幕數(shù)組 Block b; /對(duì)方快的引用 /畫布類的構(gòu)造方法 GameCanvas() rowNum = 15; columnNum = 10;
11、 maxAllowRowNum = rowNum - 2; b = new Block(this); blockInitRow = rowNum - 1; blockInitCol = columnNum/2 - 2; scrArr = new int 3232; /初始化屏幕,并將屏幕數(shù)組清零的方法 void initScr() for(int i=0;irowNum;i+) for (int j=0; jcolumnNum;j+) scrArrj=0; b.reset(); repaint(); /重新刷新畫布方法 public void paint(Graphics g) for(int
12、 i = 0; i rowNum; i+) for(int j = 0; j columnNum; j+) drawUnit(i,j,scrArrj); /畫方塊的方法 public void drawUnit(int row,int col,int type) scrArrrowcol = type; Graphics g = getGraphics(); tch(type) /表示畫方快的方法 case 0: g.setColor(Color.black);break; /以背景為顏色畫 case 1: g.setColor(Color.blue);break; /畫正在下落的方塊 cas
13、e 2: g.setColor(Color.magenta);break; /畫已經(jīng)落下的方法 g.fill3DRect(col*unitSize,getSize().height-(row+1)*unitSize,unitSize,unitSize,true); g.dispose(); public Block getBlock() return b; /返回block實(shí)例的引用 /返回屏幕數(shù)組中(row,col)位置的屬性值 public int getScrArrXY(int row,int col) if (row = rowNum | col = columnNum) return
14、(-1); else return(scrArrrowcol); /返回新塊的初始行坐標(biāo)方法 public int getInitRow() return(blockInitRow); /返回新塊的初始行坐標(biāo) /返回新塊的初始列坐標(biāo)方法 public int getInitCol() return(blockInitCol); /返回新塊的初始列坐標(biāo) /滿行刪除方法 void deleteFullLine() int full_line_num = 0; int k = 0; for (int i=0;irowNum;i+) boolean isfull = true; L1:for(int
15、j=0;jcolumnNum;j+) if(scrArrj = 0) k+; isfull = false; break L1; if(isfull) full_line_num+; if(k!=0 & k-1!=i & !isfull) for(int j = 0; j columnNum; j+) if (scrArrj = 0) drawUnit(k-1,j,0); else drawUnit(k-1,j,2); scrArrk-1j = scrArrj; for(int i = k-1 ;i rowNum; i+) for(int j = 0; j columnNum; j+) dra
16、wUnit(i,j,0); scrArrj=0; ERS_Block.score += full_line_num; ERS_Block.scoreField.setText(+ERS_Block.score); /判斷游戲是否結(jié)束方法 boolean isGameEnd() for (int col = 0 ; col columnNum; col +) if(scrArrmaxAllowRowNumcol !=0) return true; return false; public void keyTyped(KeyEvent e) public void keyReleased(KeyE
17、vent e) /處理鍵盤輸入的方法 public void keyPressed(KeyEvent e) if(!ERS_Block.isPlay) return; tch(e.getKeyCode() case KeyEvent.VK_DOWN:b.fallDown();break; case KeyEvent.VK_LEFT:b.leftMove();break; case KeyEvent.VK_RIGHT:b.rightMove();break; case KeyEvent.VK_SPACE:b.leftTurn();break; /處理控制類 class Command imple
18、ments ActionListener static final int button_play = 1; /給按鈕分配編號(hào) static final int button_levelup = 2; static final int button_leveldown = 3; static final int button_quit = 4; static final int button_pause = 5; static boolean pause_resume = true; int curButton; /當(dāng)前按鈕 GameCanvas scr; /控制按鈕類的構(gòu)造方法 Comman
19、d(int button,GameCanvas scr) curButton = button; this.scr=scr; /按鈕執(zhí)行方法 public void actionPerformed (ActionEvent e) tch(curButton) case button_play:if(!ERS_Block.isPlay) scr.initScr(); ERS_Block.isPlay = true; ERS_Block.score = 0; ERS_Block.scoreField.setText(0); ERS_Block.timer.resume(); scr.request
20、Focus(); break; case button_levelup:if(ERS_Block.level 1) ERS_Block.level-; ERS_Block.levelField.setText(+ERS_Block.level); ERS_Block.score = 0; ERS_Block.scoreField.setText(+ERS_Block.score); scr.requestFocus(); break; case button_pause:if(pause_resume) ERS_Block.timer.suspend(); pause_resume = fal
21、se; else ERS_Block.timer.resume(); pause_resume = true; scr.requestFocus(); break; case button_quit:System.exit(0); /方塊類 class Block static int pattern = 0 x0f00,0 x4444,0 x0f00,0 x4444,/用十六進(jìn)至表示,本行表示長(zhǎng)條四種狀態(tài) 0 x04e0,0 x0464,0 x00e4,0 x04c4, 0 x4620,0 x6c00,0 x4620,0 x6c00, 0 x2640,0 xc600,0 x2640,0 xc
22、600, 0 x6220,0 x1700,0 x2230,0 x0740, 0 x6440,0 x0e20,0 x44c0,0 x8e00, 0 x0660,0 x0660,0 x0660,0 x0660 ; int blockType; /塊的模式號(hào)(0-6) int turnState; /塊的翻轉(zhuǎn)狀態(tài)(0-3) int blockState; /快的下落狀態(tài) int row,col; /塊在畫布上的坐標(biāo) GameCanvas scr; /塊類的構(gòu)造方法 Block(GameCanvas scr) this.scr = scr; blockType = (int)(Math.random(
23、) * 1000)%7; turnState = (int)(Math.random() * 1000)%4; blockState = 1; row = scr.getInitRow(); col = scr.getInitCol(); /重新初始化塊,并顯示新塊 public void reset() blockType = (int)(Math.random() * 1000)%7; turnState = (int)(Math.random() * 1000)%4; blockState = 1; row = scr.getInitRow(); col = scr.getInitCol
24、(); dispBlock(1); /實(shí)現(xiàn)“塊”翻轉(zhuǎn)的方法 public void leftTurn() if(assertValid(blockType,(turnState + 1)%4,row,col) dispBlock(0); turnState = (turnState + 1)%4; dispBlock(1); /實(shí)現(xiàn)“塊”的左移的方法 public void leftMove() if(assertValid(blockType,turnState,row,col-1) dispBlock(0); col-; dispBlock(1); /實(shí)現(xiàn)塊的右移 public void
25、rightMove() if(assertValid(blockType,turnState,row,col+1) dispBlock(0); col+; dispBlock(1); /實(shí)現(xiàn)塊落下的操作的方法 public boolean fallDown() if(blockState = 2) return(false); if(assertValid(blockType,turnState,row-1,col) dispBlock(0); row-; dispBlock(1); return(true); else blockState = 2; dispBlock(2); return
26、(false); /判斷是否正確的方法 boolean assertValid(int t,int s,int row,int col) int k = 0 x8000; for(int i = 0; i 4; i+) for(int j = 0; j 4; j+) if(int)(patternts&k) != 0) int temp = scr.getScrArrXY(row-i,col+j); if (temp 1; return true; /同步顯示的方法 public synchronized void dispBlock(int s) int k = 0 x8000; for (
27、int i = 0; i 4; i+) for(int j = 0; j 1; /定時(shí)線程 class MyTimer extends Thread GameCanvas scr; public MyTimer(GameCanvas scr) this.scr = scr; public void run() while(true) try sleep(10-ERS_Block.level + 1)*100); catch(InterruptedException e) if(!scr.getBlock().fallDown() scr.deleteFullLine(); if(scr.isG
28、ameEnd() ERS_Block.isPlay = false; suspend(); else scr.getBlock().reset(); class WinListener extends WindowAdapter public void windowClosing (WindowEvent l) System.exit(0); 射擊游戲代碼效果 第一步:把如下代碼加入?yún)^(qū)域中 / Make array function MakeArray( n) this.length = n; for (var i = 1; i = n; i+) thisi = 0 return this /
29、 poor mans random number var d0 = new Date(); var r0 = d0.getSeconds(); function poor_rand() d1 = new Date(); r0 = (r0 * r0 + r0 + d1.getSeconds() % 3721 ; return r0 % width_n; / Parameters of game var height_n = 8; var width_n =5; / state of game var enemy = new MakeArray( width_n); / enemy positio
30、ns var wtime; / wait time var score; / points var gameover; / in case of gameover set to true / Make the battlefield. document.write( ); document.write( ); document.write( ); document.write( ); for( var i=0; iheight_n; i+) document.write( ); for( var j=0;jwidth_n; j+) document.write( ); document.wri
31、te( ); document.write( ); for( var j=0;jwidth_n; j+) document.write( ); document.write( ); document.write( ); document.write( ); document.write( ); / game main timer event / enemy come one step function come() var n = poor_rand(); document.fm2.elements width_n * enemyn+1 + n.checked = true; enemyn+1
32、+; if( enemyn+1 height_n) setTimeout(come(), wtime); else gameover = true; document.fm1.message.value = GAME OVER: + score ; / Fire the n th beam function fire( n) if( gameover ) return; for( var i=0; i 50) wtime -= 10; / initialize & start game function game_start() for( var n=0; nwidth_n; n+) for(
33、 var i=0; i 第二步:把區(qū)域中的內(nèi)容改為:勁舞團(tuán)游戲代碼游戲效果: 第一步:把如下代碼加入?yún)^(qū)域中!- Beginvar agt=navigator.userAgent.toLowerCase();if (agt.indexOf(mac) != -1)var a=r; elsevar a=n;var max=0;function tlist() max=tlist.arguments.length;for (i=0; imax; i+)thisi=tlist.argumentsi;tl = new tlist( o+a+ /|+a+ */ * 跳舞+a, o_+a+ 跳舞+a, _o/
34、*+a+ * |+a+ / 跳舞+a, *o_+a+ / *+a+ 跳舞+a, *+a+ _/c+a+ * 跳舞+a, _/+a+ (o_*+a+ * 跳舞+a, /+a+ |+a+ */o* 跳舞+a, _+a+ (+a+ */o* 跳舞+a, +a+ o|* 跳舞+a, *+a+ o|_/+a+ */ 跳舞+a, *+a+ _o|_+a+ * 跳舞+a, _o/*+a+ * |+a+ / 跳舞+a, *o/*+a+ |+a+ / 跳舞+a, c/*+a+ +a+ */ 跳舞+a, c_+a+ 跳舞+a, c/*+a+ /(_+a+ * / 跳舞+a, _o/*+a+ * (_+a+ 跳舞+
35、a, _o_+a+ * / *+a+ 跳舞+a, *_o_+a+ | *+a+ 跳舞+a, *_c_*+a+ |_+a+ 跳舞+a, *_c_*+a+ _|_+a+ 跳舞+a, +a+ *_c_*+a+ _)_ 跳舞+a, +a+ *c/*+a+ _)_ 跳舞+a);var x=0;function tick() document.animation.cheerleader.value = + a +tlx;x+;if (x != max)setTimeout(tick(), 200);elsex = 0;/ End -textarea name=cheerleader rows=5 cols
36、=20&rt;/textarea&rt;第二步:把區(qū)域中的內(nèi)容改為:鼠標(biāo)移動(dòng)代碼!-將以下代碼加入HTML的之間- var nDots = 7;var Xpos = 0;var Ypos = 0;var DELTAT = .01;var SEGLEN = 10;var SPRINGK = 10;var MASS = 1;var XGRAVITY = 0;var YGRAVITY = 50;var RESISTANCE = 10;var STOPVEL = 0.1;var STOPACC = 0.1;var DOTSIZE = 11;var BOUNCE = 0.75;var isNetscap
37、e = navigator.appName=Netscape;var followmouse = true;var dots = new Array();init();function init() var i = 0; for (i = 0; i nDots; i+) dotsi = new dot(i); if (!isNetscape) for (i = 0; i nDots; i+) dotsi.obj.left = dotsi.X; dotsi.obj.top = dotsi.Y; if (isNetscape) startanimate(); else setTimeout(sta
38、rtanimate(), 1000); function dot(i) this.X = Xpos; this.Y = Ypos; this.dx = 0; this.dy = 0; if (isNetscape) this.obj = eval(document.dot + i); else this.obj = eval(dot + i + .style); function startanimate() setInterval(animate(), 20);function setInitPositions(dots) var startloc = document.all.tags(L
39、I); var i = 0; for (i = 0; i startloc.length & i SEGLEN) var springF = SPRINGK * (len - SEGLEN); spring.X += (dx / len) * springF; spring.Y += (dy / len) * springF; function animate() var start = 0; if (followmouse) dots0.X = Xpos; dots0.Y = Ypos; start = 1; for (i = start ; i 0) springForce(i-1, i,
40、 spring); if (i (nDots - 1) springForce(i+1, i, spring); var resist = new vec(-dotsi.dx * RESISTANCE, -dotsi.dy * RESISTANCE); var accel = new vec(spring.X + resist.X)/MASS + XGRAVITY, (spring.Y + resist.Y)/ MASS + YGRAVITY); dotsi.dx += (DELTAT * accel.X); dotsi.dy += (DELTAT * accel.Y); if (Math.a
41、bs(dotsi.dx) STOPVEL & Math.abs(dotsi.dy) STOPVEL & Math.abs(accel.X) STOPACC & Math.abs(accel.Y) = height - DOTSIZE - 1) if (dotsi.dy 0) dotsi.dy = BOUNCE * -dotsi.dy; dotsi.Y = height - DOTSIZE - 1; if (dotsi.X = width - DOTSIZE) if (dotsi.dx 0) dotsi.dx = BOUNCE * -dotsi.dx; dotsi.X = width - DOT
42、SIZE - 1; if (dotsi.X 0) if (dotsi.dx 0) dotsi.dx = BOUNCE * -dotsi.dx; dotsi.X = 0; dotsi.obj.left = dotsi.X; dotsi.obj.top = dotsi.Y; 附錄資料:如何處理Java異常及常見異常六種異常處理的陋習(xí)你覺得自己是一個(gè)Java專家嗎?是否肯定自己已經(jīng)全面掌握了Java的異常處理機(jī)制?在下面這段代碼中,你能夠迅速找出異常處理的六個(gè)問(wèn)題嗎? 1 OutputStreamWriter out = . 2 java.sql.Connection conn = . 3 try
43、/ 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(Exception ex) / 16 17 ex.printStackTrace(); /,
44、18 作為一個(gè)Java程序員,你至少應(yīng)該能夠找出兩個(gè)問(wèn)題。但是,如果你不能找出全部六個(gè)問(wèn)題,請(qǐng)繼續(xù)閱讀本文。 本文討論的不是Java異常處理的一般性原則,因?yàn)檫@些原則已經(jīng)被大多數(shù)人熟知。我們要做的是分析各種可稱為“反例”(anti-pattern)的違背優(yōu)秀編碼規(guī)范的常見壞習(xí)慣,幫助讀者熟悉這些典型的反面例子,從而能夠在實(shí)際工作中敏銳地察覺和避免這些問(wèn)題。 反例之一:丟棄異常 代碼:15行-18行。 這段代碼捕獲了異常卻不作任何處理,可以算得上Java編程中的殺手。從問(wèn)題出現(xiàn)的頻繁程度和禍害程度來(lái)看,它也許可以和C/C+程序的一個(gè)惡名遠(yuǎn)播的問(wèn)題相提并論?不檢查緩沖區(qū)是否已滿。如果你看到了這種丟
45、棄(而不是拋出)異常的情況,可以百分之九十九地肯定代碼存在問(wèn)題(在極少數(shù)情況下,這段代碼有存在的理由,但最好加上完整的注釋,以免引起別人誤解)。 這段代碼的錯(cuò)誤在于,異常(幾乎)總是意味著某些事情不對(duì)勁了,或者說(shuō)至少發(fā)生了某些不尋常的事情,我們不應(yīng)該對(duì)程序發(fā)出的求救信號(hào)保持沉默和無(wú)動(dòng)于衷。調(diào)用一下printStackTrace算不上“處理異?!?。不錯(cuò),調(diào)用printStackTrace對(duì)調(diào)試程序有幫助,但程序調(diào)試階段結(jié)束之后, printStackTrace就不應(yīng)再在異常處理模塊中擔(dān)負(fù)主要責(zé)任了。 丟棄異常的情形非常普遍。打開JDK的ThreadDeath類的文檔,可以看到下面這段說(shuō)明:“特別
46、地,雖然出現(xiàn)ThreadDeath是一種正常的情形,但ThreadDeath類是Error而不是Exception的子類,因?yàn)樵S多應(yīng)用會(huì)捕獲所有的Exception然后丟棄它不再理睬?!边@段話的意思是,雖然ThreadDeath代表的是一種普通的問(wèn)題,但鑒于許多應(yīng)用會(huì)試圖捕獲所有異常然后不予以適當(dāng)?shù)奶幚?,所以JDK把 ThreadDeath定義成了Error的子類,因?yàn)镋rror類代表的是一般的應(yīng)用不應(yīng)該去捕獲的嚴(yán)重問(wèn)題??梢?,丟棄異常這一壞習(xí)慣是如此常見,它甚至已經(jīng)影響到了Java本身的設(shè)計(jì)。 那么,應(yīng)該怎樣改正呢?主要有四個(gè)選擇: 1、處理異常。針對(duì)該異常采取一些行動(dòng),例如修正問(wèn)題、提醒某
47、個(gè)人或進(jìn)行其他一些處理,要根據(jù)具體的情形確定應(yīng)該采取的動(dòng)作。再次說(shuō)明,調(diào)用printStackTrace算不上已經(jīng)“處理好了異?!薄?2、重新拋出異常。處理異常的代碼在分析異常之后,認(rèn)為自己不能處理它,重新拋出異常也不失為一種選擇。 3、把該異常轉(zhuǎn)換成另一種異常。大多數(shù)情況下,這是指把一個(gè)低級(jí)的異常轉(zhuǎn)換成應(yīng)用級(jí)的異常(其含義更容易被用戶了解的異常)。 4、不要捕獲異常。 結(jié)論一:既然捕獲了異常,就要對(duì)它進(jìn)行適當(dāng)?shù)奶幚?。不要捕獲異常之后又把它丟棄,不予理睬。 反例之二:不指定具體的異常 代碼:15行。 許多時(shí)候人們會(huì)被這樣一種“美妙的”想法吸引:用一個(gè)catch語(yǔ)句捕獲所有的異常。最常見的情形就
48、是使用catch(Exception ex)語(yǔ)句。但實(shí)際上,在絕大多數(shù)情況下,這種做法不值得提倡。為什么呢? 要理解其原因,我們必須回顧一下catch語(yǔ)句的用途。catch語(yǔ)句表示我們預(yù)期會(huì)出現(xiàn)某種異常,而且希望能夠處理該異常。異常類的作用就是告訴 Java編譯器我們想要處理的是哪一種異常。由于絕大多數(shù)異常都直接或間接從java.lang.Exception派生,catch (Exception ex)就相當(dāng)于說(shuō)我們想要處理幾乎所有的異常。 再來(lái)看看前面的代碼例子。我們真正想要捕獲的異常是什么呢?最明顯的一個(gè)是SQLException,這是JDBC操作中常見的異常。另一個(gè)可能的異常是IOExc
49、eption,因?yàn)樗僮鱋utputStreamWriter。顯然,在同一個(gè)catch塊中處理這兩種截然不同的異常是不合適的。如果用兩個(gè)catch塊分別捕獲SQLException和IOException就要好多了。這就是說(shuō),catch語(yǔ)句應(yīng)當(dāng)盡量指定具體的異常類型,而不應(yīng)該指定涵蓋范圍太廣的Exception類。 另一方面,除了這兩個(gè)特定的異常,還有其他許多異常也可能出現(xiàn)。例如,如果由于某種原因,executeQuery返回了null,該怎么辦?答案是讓它們繼續(xù)拋出,即不必捕獲也不必處理。實(shí)際上,我們不能也不應(yīng)該去捕獲可能出現(xiàn)的所有異常,程序的其他地方還有捕獲異常的機(jī)會(huì)?直至最后由JVM處
50、理。 結(jié)論二:在catch語(yǔ)句中盡可能指定具體的異常類型,必要時(shí)使用多個(gè)catch。不要試圖處理所有可能出現(xiàn)的異常。 反例之三:占用資源不釋放 代碼:3行-14行。 異常改變了程序正常的執(zhí)行流程。這個(gè)道理雖然簡(jiǎn)單,卻常常被人們忽視。如果程序用到了文件、Socket、JDBC連接之類的資源,即使遇到了異常,也要正確釋放占用的資源。為此,Java提供了一個(gè)簡(jiǎn)化這類操作的關(guān)鍵詞finally。 finally是樣好東西:不管是否出現(xiàn)了異常,F(xiàn)inally保證在try/catch/finally塊結(jié)束之前,執(zhí)行清理任務(wù)的代碼總是有機(jī)會(huì)執(zhí)行。遺憾的是有些人卻不習(xí)慣使用finally。 當(dāng)然,編寫fina
51、lly塊應(yīng)當(dāng)多加小心,特別是要注意在finally塊之內(nèi)拋出的異常?這是執(zhí)行清理任務(wù)的最后機(jī)會(huì),盡量不要再有難以處理的錯(cuò)誤。 結(jié)論三:保證所有資源都被正確釋放。充分運(yùn)用finally關(guān)鍵詞。反例之四:不說(shuō)明異常的詳細(xì)信息 代碼:3行-18行。 仔細(xì)觀察這段代碼:如果循環(huán)內(nèi)部出現(xiàn)了異常,會(huì)發(fā)生什么事情?我們可以得到足夠的信息判斷循環(huán)內(nèi)部出錯(cuò)的原因嗎?不能。我們只能知道當(dāng)前正在處理的類發(fā)生了某種錯(cuò)誤,但卻不能獲得任何信息判斷導(dǎo)致當(dāng)前錯(cuò)誤的原因。 printStackTrace的堆棧跟蹤功能顯示出程序運(yùn)行到當(dāng)前類的執(zhí)行流程,但只提供了一些最基本的信息,未能說(shuō)明實(shí)際導(dǎo)致錯(cuò)誤的原因,同時(shí)也不易解讀。 因
52、此,在出現(xiàn)異常時(shí),最好能夠提供一些文字信息,例如當(dāng)前正在執(zhí)行的類、方法和其他狀態(tài)信息,包括以一種更適合閱讀的方式整理和組織printStackTrace提供的信息。 結(jié)論四:在異常處理模塊中提供適量的錯(cuò)誤原因信息,組織錯(cuò)誤信息使其易于理解和閱讀。 反例之五:過(guò)于龐大的try塊 代碼:3行-14行。 經(jīng)??梢钥吹接腥税汛罅康拇a放入單個(gè)try塊,實(shí)際上這不是好習(xí)慣。這種現(xiàn)象之所以常見,原因就在于有些人圖省事,不愿花時(shí)間分析一大塊代碼中哪幾行代碼會(huì)拋出異常、異常的具體類型是什么。把大量的語(yǔ)句裝入單個(gè)巨大的try塊就象是出門旅游時(shí)把所有日常用品塞入一個(gè)大箱子,雖然東西是帶上了,但要找出來(lái)可不容易。
53、一些新手常常把大量的代碼放入單個(gè)try塊,然后再在catch語(yǔ)句中聲明Exception,而不是分離各個(gè)可能出現(xiàn)異常的段落并分別捕獲其異常。這種做法為分析程序拋出異常的原因帶來(lái)了困難,因?yàn)橐淮蠖未a中有太多的地方可能拋出Exception。 結(jié)論五:盡量減小try塊的體積。 反例之六:輸出數(shù)據(jù)不完整 代碼:7行-11行。 不完整的數(shù)據(jù)是Java程序的隱形殺手。仔細(xì)觀察這段代碼,考慮一下如果循環(huán)的中間拋出了異常,會(huì)發(fā)生什么事情。循環(huán)的執(zhí)行當(dāng)然是要被打斷的,其次, catch塊會(huì)執(zhí)行?就這些,再也沒(méi)有其他動(dòng)作了。已經(jīng)輸出的數(shù)據(jù)怎么辦?使用這些數(shù)據(jù)的人或設(shè)備將收到一份不完整的(因而也是錯(cuò)誤的)數(shù)據(jù),
54、卻得不到任何有關(guān)這份數(shù)據(jù)是否完整的提示。對(duì)于有些系統(tǒng)來(lái)說(shuō),數(shù)據(jù)不完整可能比系統(tǒng)停止運(yùn)行帶來(lái)更大的損失。 較為理想的處置辦法是向輸出設(shè)備寫一些信息,聲明數(shù)據(jù)的不完整性;另一種可能有效的辦法是,先緩沖要輸出的數(shù)據(jù),準(zhǔn)備好全部數(shù)據(jù)之后再一次性輸出。 結(jié)論六:全面考慮可能出現(xiàn)的異常以及這些異常對(duì)執(zhí)行流程的影響。 改寫后的代碼 根據(jù)上面的討論,下面給出改寫后的代碼。也許有人會(huì)說(shuō)它稍微有點(diǎn)?嗦,但是它有了比較完備的異常處理機(jī)制。 OutputStreamWriter out = . java.sql.Connection conn = . try Statement stat = conn.createS
55、tatement(); 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ù)時(shí)出現(xiàn)SQL錯(cuò)誤, sqlex); catch(IOException ioex) throw new Applica
56、tionException(寫入數(shù)據(jù)時(shí)出現(xiàn)IO錯(cuò)誤, ioex); finally if (conn != null) try conn.close(); catch(SQLException sqlex2) System.err(this.getClass().getName() + .mymethod - 不能關(guān)閉數(shù)據(jù)庫(kù)連接: + sqlex2.toString(); if (out != null) try out.close(); catch(IOException ioex2) System.err(this.getClass().getName() + .mymethod - 不能
57、關(guān)閉輸出文件 + ioex2.toString(); 本文的結(jié)論不是放之四海皆準(zhǔn)的教條,有時(shí)常識(shí)和經(jīng)驗(yàn)才是最好的老師。如果你對(duì)自己的做法沒(méi)有百分之百的信心,務(wù)必加上詳細(xì)、全面的注釋。 另一方面,不要笑話這些錯(cuò)誤,不妨問(wèn)問(wèn)你自己是否真地徹底擺脫了這些壞習(xí)慣。即使最有經(jīng)驗(yàn)的程序員偶爾也會(huì)誤入歧途,原因很簡(jiǎn)單,因?yàn)樗鼈兇_確實(shí)實(shí)帶來(lái)了“方便”。所有這些反例都可以看作Java編程世界的惡魔,它們美麗動(dòng)人,無(wú)孔不入,時(shí)刻誘惑著你。也許有人會(huì)認(rèn)為這些都屬于雞皮蒜毛的小事,不足掛齒,但請(qǐng)記?。何鹨詯盒《鵀橹?,勿以善小而不為。下面是一些 java異常集 算術(shù)異常類:ArithmeticExecption空指針異
58、常類:NullPointerException類型強(qiáng)制轉(zhuǎn)換異常:ClassCastException數(shù)組負(fù)下標(biāo)異常:NegativeArrayException數(shù)組下標(biāo)越界異常:ArrayIndexOutOfBoundsException違背安全原則異常:SecturityException文件已結(jié)束異常:EOFException文件未找到異常:FileNotFoundException字符串轉(zhuǎn)換為數(shù)字異常:NumberFormatException操作數(shù)據(jù)庫(kù)異常:SQLException輸入輸出異常:IOException方法未找到異常:NoSuchMethodExceptionjava.l
59、ang.AbstractMethodError抽象方法錯(cuò)誤。當(dāng)應(yīng)用試圖調(diào)用抽象方法時(shí)拋出。java.lang.AssertionError斷言錯(cuò)。用來(lái)指示一個(gè)斷言失敗的情況。java.lang.ClassCircularityError類循環(huán)依賴錯(cuò)誤。在初始化一個(gè)類時(shí),若檢測(cè)到類之間循環(huán)依賴則拋出該異常。java.lang.ClassFormatError類格式錯(cuò)誤。當(dāng)Java虛擬機(jī)試圖從一個(gè)文件中讀取Java類,而檢測(cè)到該文件的內(nèi)容不符合類的有效格式時(shí)拋出。java.lang.Error錯(cuò)誤。是所有錯(cuò)誤的基類,用于標(biāo)識(shí)嚴(yán)重的程序運(yùn)行問(wèn)題。這些問(wèn)題通常描述一些不應(yīng)被應(yīng)用程序捕獲的反常情況。ja
60、va.lang.ExceptionInInitializerError初始化程序錯(cuò)誤。當(dāng)執(zhí)行一個(gè)類的靜態(tài)初始化程序的過(guò)程中,發(fā)生了異常時(shí)拋出。靜態(tài)初始化程序是指直接包含于類中的static語(yǔ)句段。java.lang.IllegalAccessError違法訪問(wèn)錯(cuò)誤。當(dāng)一個(gè)應(yīng)用試圖訪問(wèn)、修改某個(gè)類的域(Field)或者調(diào)用其方法,但是又違反域或方法的可見性聲明,則拋出該異常。java.lang.IncompatibleClassChangeError不兼容的類變化錯(cuò)誤。當(dāng)正在執(zhí)行的方法所依賴的類定義發(fā)生了不兼容的改變時(shí),拋出該異常。一般在修改了應(yīng)用中的某些類的聲明定義而沒(méi)有對(duì)整個(gè)應(yīng)用重新編譯而直
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 高效決策機(jī)制在國(guó)企中的實(shí)踐與應(yīng)用
- 社交媒體與跨境電商品牌傳播
- 白酒行業(yè)轉(zhuǎn)型升級(jí)未來(lái)展望及發(fā)展趨勢(shì)
- 智能農(nóng)業(yè)設(shè)備在油菜種植中的創(chuàng)新應(yīng)用
- 2025年英語(yǔ)專業(yè)八級(jí)文學(xué)批評(píng)閱讀理解能力測(cè)試卷
- 新一代信息技術(shù)在農(nóng)業(yè)產(chǎn)業(yè)中的應(yīng)用展望
- 智能化健康管理系統(tǒng)的構(gòu)建與實(shí)踐
- 貨場(chǎng)倉(cāng)儲(chǔ)物流項(xiàng)目風(fēng)險(xiǎn)管理
- 老舊市政供水管網(wǎng)更新改造項(xiàng)目選址
- 優(yōu)雅交往藝術(shù)
- 國(guó)家開放大學(xué)本科《公共部門人力資源管理》期末紙質(zhì)考試總題庫(kù)2025版
- 江蘇省南通一中2025屆高三第四次模擬考試生物試卷含解析
- 浙江省杭州市2023-2024學(xué)年高二下學(xué)期6月期末英語(yǔ)試題
- 凈水廠新建工藝設(shè)備安裝及給水管網(wǎng)安裝工程施工方案
- JB-T14451-2023《鋼質(zhì)鍛件鍛造生產(chǎn)能源消耗限額及評(píng)價(jià)方法》
- 2023年海南中考化學(xué)試題及答案
- 果蔬保鮮技術(shù)發(fā)展趨勢(shì)分析報(bào)告
- 《揚(yáng)州慢》教學(xué)課件
- 施工現(xiàn)場(chǎng)視頻監(jiān)控系統(tǒng)施工方案
- (正式版)JTT 1495-2024 公路水運(yùn)危險(xiǎn)性較大工程安全專項(xiàng)施工方案審查規(guī)程
- 《征兵入伍應(yīng)征公民體格檢查標(biāo)準(zhǔn)條文釋義》
評(píng)論
0/150
提交評(píng)論