項目 | 內容 |
這個做業屬於哪一個課程 | https://www.cnblogs.com/nwnu-daizh/ |
這個做業要求在哪裏 | https://www.cnblogs.com/nwnu-daizh/p/11778090.html |
做業的學習目標 | 1.掌握java異常處理技術;html 2.瞭解斷言的用法;java 3.瞭解日誌的用途;程序員 4.掌握程序基礎調試技巧。編程 |
第一部分:第七章理論知識數組
1、異常網絡
(1) 異常:在程序的執行過程當中所發生的異常事件,它中斷指令的正常執行。app
(2)異常處理的任務就是將控制權從錯誤產生的地方轉移給可以處理這種狀況的錯誤處理器。less
(3)程序中可能出現的錯誤和問題:a.用戶輸入錯誤。b.設備錯誤。c.物理限制。d.代碼錯誤。dom
(4)Java中把程序運行時可能出現的錯誤分爲兩類:ide
A:非致命異常:經過某種修正後程序還能繼續執行。如:文件不存在,網絡斷開,無效的數組下標,磁盤滿等。Java中提供了一種獨特的異常處理機制處理這類 錯誤。
B:致命異常:程序用到了很是嚴重的不正常的狀態,不能簡單執行恢復,是致命性錯誤。如:內存耗盡,系統內部錯誤。這種錯誤程序自己沒法解決。
(5)Java中全部異常類都直接或間接地繼承於Throwable類。除內置異常類外,程序員可自定義異常類。
(6) Java的異常類可分爲兩大類:
A:Error類:描述了java運行時系統的內部錯誤和資源耗盡錯誤。應用程序不該該捕獲這類異常,也不會拋出這種異常。(很難恢復的嚴重錯誤,通常不禁程序處理)
B:Exception類:分爲兩分支,一個分支派生於Runtime Exception;另外一個分支包含其餘異常。(程序設計或者實現上的問題,如數組越界等)。其餘異常:一般是由環境引發的,而且能夠被處理。
(7)Java異常層次結構簡化示意圖以下:
(8)聲明拋出異常:若是一個方法可能會生成一些異常,可是該方法並不確切知道如何對這些異常進行處理,此時,這個方法就聲明拋出異常。
A:聲明拋出異常在方法聲明中用throws子句中來聲明,throws子句能夠同時指多個異常,說明該方法將不對這些異常進行處理,而是聲明拋出它們。
B:如下四種狀況用throws子句聲明拋出異常:
—方法調用了一個拋出已檢查異常的方法;
—程序運行過程當中可能發生錯誤,而且利用throw語句拋出一個已檢查異常對象
—程序出現錯誤
—Java虛擬機和運行時庫出現的內部異常。
C:一個方法必須聲明該方法全部可能拋出的已檢查異常,而未檢查異常要麼不可控制(Error),要麼應該避免發生(RuntimeException).
D:若是方法沒有聲明全部可能發生的已檢查異常,編譯器會給出一個錯誤消息。
(9) 當Java應用程序出現錯誤時,會根據錯誤類型產生一個異常對象,這個對象包含了異常的類型和錯誤出現時程序所處的狀態信息。把異常對象遞交給Java編譯器的過程稱爲拋出。
(10)拋出異常要生成異常對象,異常對象可由某些類的實例生成,也能夠由JVM生成。
(11)拋出異常對象經過throw語句來實現。
(12)建立異常類
A:自定義異常類:定義一個派生於Exception的直接或者間接子類。自定義的異常類應該包括兩個構造器:a:默認構造器b:帶有詳細描述信息的構造器。
二:捕獲異常
(1)捕獲:程序運行期間,異常發生時,Java運行系統從異常生成的代碼塊開始,尋找相應的異常處理代碼,並將異常交給該方法處理。
(2)某個異常發生時,若程序沒有在任何地方進行該異常的捕獲,則程序就會終止執行,並在控制檯上輸出異常信息。
(3)若要捕獲一個異常,須要在程序中設置一個 try/catch/ finally塊:
–try語句括住可能拋出異常的代碼段。
–catch語句指明要捕獲的異常及相應的處理代碼。
–finally語句指明必須執行的程序塊。
(4)try子句:捕獲異常的第一步是用try{….}子句選定捕獲異常的代碼範圍,由try所限定的代碼塊中的語句,在執行過程當中可能會自動生成異常對象並拋出。
(5)catch子句:
a)catch塊是對異常對象進行處理的代碼;
b)每一個try代碼塊能夠伴隨一個或多個catch語句,用於處理try代碼塊中所生成的格類異常事件;
c)catch語句只須要一個形式參數指明它所能捕獲的異常類對象,這個異常類必須是Throwable的子類,運行時系統經過參數值把被拋出的異常傳遞給catch塊;
d)catch塊能夠經過異常對象調用類Throwable所提供的方法。
---getMessage()用來獲得有關異常事件的信息;
---printStackTrace()用來跟蹤異常事件發生時執行堆棧的內容。
e)能夠在一個try塊中捕獲多個異常類型,每一個異常類型須要一個單獨的catch子句。
(6)finally 子句:
A:捕獲異常的最後一步是經過finally語句爲異常處理提供一個統一出口,使得控制流程在轉到程序其餘部分之前,可以對程序的狀態作統一的管理;
B:無論異常是否被捕獲,finally子句中的代碼都會被執行。
(7)異常處理中分析堆棧跟蹤元素:
A:堆棧跟蹤(staack trace)是程序執行中一個方法調用過程的列表,它包含了程序執行過程當中的特定位置;
B:可用Throwable類的printStack Trace方法訪問堆棧跟蹤的文本描述信息。
三:使用異常機制的建議:
(1)積極處理方法:確切知道如何處理的異常應該捕獲
(2)消極處理方法:不知道如何去處理的異常聲明拋出。
四:異常處理的原則
(1)異常處理不能代替簡單的條件檢測,只在異常狀況下使用異常機制。例如:上百萬次地對一個空棧進行退棧操做。
(2)程序代碼不要過度細化異常,儘可能將有可能產生異常的語句放在--個try語句塊中。
(3)拋出的異常類型儘量明確。
(4)不要壓制異常,對於不多發生的異常,應該將其關閉。
(5) 早拋出,晚捕獲,儘可能讓高層次的方法通告用戶發生了錯誤。
五:斷言
1.斷言:是程序的開發和測試階段用於插入一些代碼錯誤檢測語句的工具。
2.斷言(assert) 語法以下:
1)assert 條件
或者
2)assert 條件:表達式
這兩個形式都會對布爾「條件」進行判斷,若是判斷結果爲假(false),說明程序已經處於不正確的狀態下,系統則拋出AssertionError,給出警告而且退出。在第二種形式中,「 表達式」會傳入AssertionError的構造函數中並轉成一個消息字符串。
第二部分:實驗部分
實驗1:用命令行與IDE兩種環境下編輯調試運行源程序ExceptionDemo1、ExceptionDemo2,結合程序運行結果理解程序,掌握未檢查異常和已檢查異常的區別。
//異常示例1 public class ExceptionDemo1 { public static void main(String args[]) { int a = 0; System.out.println(5 / a); } }
在命令行環境下運行結果以下:
在ID環境下程序運行結果以下:
//異常示例2 import java.io.*; public class ExceptionDemo2 { public static void main(String args[]) { FileInputStream fis=new FileInputStream("text.txt");//JVM自動生成異常對象 int b; while((b=fis.read())!=-1) { System.out.print(b); } fis.close(); } }
該程序存在文件找不到的錯誤,對該程序修改後,修改後代碼以下:
//異常示例2 import java.io.*; public class ExceptionDemo2 { public static void main(String args[]) throws IOException { FileInputStream fis=new FileInputStream("text.txt");//JVM自動生成異常對象 int b; while((b=fis.read())!=-1) { System.out.print(b); } fis.close(); } }
該程序在命令行環境下運行結果以下:
在ID環境下運行結果以下:
實驗2: 導入如下示例程序,測試程序並進行代碼註釋。
測試程序1:
1)在elipse IDE中編輯、編譯、調試運行教材281頁7-1,結合程序運行結果理解程序;
2)在程序中相關代碼處添加新知識的註釋;
3)掌握Throwable類的堆棧跟蹤方法;
代碼以下:
1 package stackTrace; 2 3 import java.util.*; 4 5 /** 6 * A program that displays a trace feature of a recursive method call. 7 * @version 1.10 2017-12-14 8 * @author Cay Horstmann 9 */ 10 public class StackTraceTest 11 { 12 /** 13 * Computes the factorial of a number 14 * @param n a non-negative integer 15 * @return n! = 1 * 2 * . . . * n 16 */ 17 public static int factorial(int n) //求階乘 18 { 19 System.out.println("factorial(" + n + "):"); 20 var walker = StackWalker.getInstance(); //建立對象時調用堆棧的跟蹤 21 walker.forEach(System.out::println); //調用對象walker的foreach循環 22 int r; 23 if (n <= 1) r = 1; 24 else r = n * factorial(n - 1); //計算n的階乘須要去調用n-1的階乘 25 System.out.println("return " + r); 26 return r; 27 } 28 29 public static void main(String[] args) 30 { 31 try (var in = new Scanner(System.in)) //try語句塊 32 { 33 System.out.print("Enter n: "); 34 int n = in.nextInt(); 35 factorial(n); 36 } 37 } 38 }
程序運行結果以下:
測試程序2:
1) Java語言的異常處理有積極處理方法和消極處理兩種方式;
2)下列兩個簡單程序範例給出了兩種異常處理的代碼格式。在elipse IDE中編輯、調試運行源程序ExceptionTest.java,將程序中的text文件更換爲身份證號.txt,要求將文件內容讀入內容,並在控制檯顯示;
3)掌握兩種異常處理技術的特色。
//積極處理方式 import java.io.*;
class ExceptionTest { public static void main (string args[]) { try{ FileInputStream fis=new FileInputStream("text.txt"); } catch(FileNotFoundExcption e) { …… } …… } } |
//消極處理方式
import java.io.*; class ExceptionTest { public static void main (string args[]) throws FileNotFoundExcption { FileInputStream fis=new FileInputStream("text.txt"); } } |
積極處理方式的代碼以下:
1 import java.io.*; 2 3 class ExceptionTest { 4 public static void main (String args[]) 5 { 6 7 try{ 8 FileInputStream fis=new FileInputStream("D://身份證號.txt"); 9 BufferedReader in = new BufferedReader(new InputStreamReader(fis)); 10 String s = new String(); 11 while ((s = in.readLine()) != null) { 12 System.out.println(s); 13 } 14 in.close(); 15 fis.close(); 16 } 17 catch (FileNotFoundException e) { 18 System.out.println("文件未找到"); 19 e.printStackTrace(); 20 } catch (IOException e) { 21 System.out.println("文件讀取錯誤"); 22 e.printStackTrace(); 23 } 24 } 25 }
消極處理方式的代碼以下:
1 import java.io.*; 2 3 public class ExceptionTest { 4 public static void main (String args[]) throws IOException 5 { 6 7 try{ 8 FileInputStream fis=new FileInputStream("D://身份證號.txt"); 9 BufferedReader in = new BufferedReader(new InputStreamReader(fis)); 10 String s = new String(); 11 while ((s = in.readLine()) != null) { 12 System.out.println(s); 13 } 14 in.close(); 15 fis.close(); 16 17 } 18 finally { 19 return ; 20 } 21 22 } 23 }
程序運行結果以下:
實驗3: 編程練習
1)編寫一個計算器類,能夠完成加、減、乘、除的操做;
2)利用計算機類,設計一個小學生100之內數的四則運算練習程序,由計算機隨機產生10道加減乘除練習題,學生輸入答案,由程序檢查答案是否正確,每道題正確計10分,錯誤不計分,10道題測試結束後給出測試總分;
3)將程序中測試練習題及學生答題結果輸出到文件,文件名爲test.txt;
4)在以上程序適當位置加入異常捕獲代碼。
分析:
程序代碼以下:
package CounterTest; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.util.Scanner; public class counter { public static void main(String[] args) { Scanner in=new Scanner(System.in); sf sf=new sf(); PrintWriter output = null; try { output = new PrintWriter("test.txt"); } catch (FileNotFoundException e) { e.printStackTrace(); } int sum = 0; for (int i = 1; i < 11; i++) { int a = (int) Math.round(Math.random() * 100); int b = (int) Math.round(Math.random() * 100); int num = (int) Math.round(Math.random() * 4); switch(num) { case 1: System.out.println(i+": "+a+"/"+b+"="); while(b==0){ b = (int) Math.round(Math.random() * 100); } double c = in.nextDouble(); output.println(a+"/"+b+"="+c); if (c == sf.chu_fa(a, b)) { sum += 10; System.out.println("恭喜答案正確"); } else { System.out.println("抱歉,答案錯誤"); } break; case 2: System.out.println(i+": "+a+"*"+b+"="); int c1 = in.nextInt(); output.println(a+"*"+b+"="+c1); if (c1 == sf.chen_fa(a, b)) { sum += 10; System.out.println("恭喜答案正確"); } else { System.out.println("抱歉,答案錯誤"); }break; case 3: System.out.println(i+": "+a+"+"+b+"="); int c2 = in.nextInt(); output.println(a+"+"+b+"="+c2); if (c2 == sf.jia_fa(a, b)) { sum += 10; System.out.println("恭喜答案正確"); } else { System.out.println("抱歉,答案錯誤"); }break ; case 4: System.out.println(i+": "+a+"-"+b+"="); int c3 = in.nextInt(); output.println(a+"-"+b+"="+c3); if (c3 == sf.jian_fa(a, b)) { sum += 10; System.out.println("恭喜答案正確"); } else { System.out.println("抱歉,答案錯誤"); }break ; } } System.out.println("成績"+sum); output.println("成績:"+sum); output.close(); } }
package CounterTest; public class sf { private int a; private int b; public int jia_fa(int a,int b) { return a+b; } public int jian_fa(int a,int b) { return a-b; } public int chen_fa(int a,int b) { return a*b; } public int chu_fa(int a,int b) { if(b!=0) return a/b; else return 0; } }
程序運行結果以下:
實驗4:斷言、日誌、程序調試技巧驗證明驗。
實驗程序1:
//斷言程序示例 public class AssertDemo { public static void main(String[] args) { test1(-5); test2(-3); }
private static void test1(int a){ assert a > 0; System.out.println(a); } private static void test2(int a){ assert a > 0 : "something goes wrong here, a cannot be less than 0"; System.out.println(a); } } |
1)在elipse下調試程序AssertDemo,結合程序運行結果理解程序;
2)註釋語句test1(-5);後從新運行程序,結合程序運行結果理解程序;
3)掌握斷言的使用特色及用法。
程序運行結果以下:
註釋語句test1(-5);後代碼以下:
package project; //斷言程序示例 public class AssertDemo { public static void main(String[] args) { //test1(-5); test2(-3); } private static void test1(int a){ assert a > 0; System.out.println(a); } private static void test2(int a){ assert a > 0 : "something goes wrong here, a cannot be less than 0"; System.out.println(a); } }
運行結果以下:
實驗程序2:
2)用JDK命令調試運行教材298頁-300頁程序7-2,結合程序運行結果理解程序;
並掌握Java日誌系統的用途及用法。
程序代碼以下:
1 package logging; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.io.*; 6 import java.util.logging.*; 7 import javax.swing.*; 8 9 /** 10 * A modification of the image viewer program that logs various events. 11 * @version 1.03 2015-08-20 12 * @author Cay Horstmann 13 */ 14 public class LoggingImageViewer 15 { 16 public static void main(String[] args) 17 { 18 if (System.getProperty("java.util.logging.config.class") == null 19 && System.getProperty("java.util.logging.config.file") == null) 20 { 21 try 22 { 23 Logger.getLogger("com.horstmann.corejava").setLevel(Level.ALL); 24 final int LOG_ROTATION_COUNT = 10; 25 var handler = new FileHandler("%h/LoggingImageViewer.log", 0, LOG_ROTATION_COUNT); 26 Logger.getLogger("com.horstmann.corejava").addHandler(handler); 27 } 28 catch (IOException e) 29 { 30 Logger.getLogger("com.horstmann.corejava").log(Level.SEVERE, 31 "Can't create log file handler", e); 32 } 33 } 34 35 EventQueue.invokeLater(() -> 36 { 37 var windowHandler = new WindowHandler(); 38 windowHandler.setLevel(Level.ALL); 39 Logger.getLogger("com.horstmann.corejava").addHandler(windowHandler); 40 41 var frame = new ImageViewerFrame(); 42 frame.setTitle("LoggingImageViewer"); 43 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 44 45 Logger.getLogger("com.horstmann.corejava").fine("Showing frame"); 46 frame.setVisible(true); 47 }); 48 } 49 } 50 51 /** 52 * The frame that shows the image. 53 */ 54 class ImageViewerFrame extends JFrame 55 { 56 private static final int DEFAULT_WIDTH = 300; 57 private static final int DEFAULT_HEIGHT = 400; 58 59 private JLabel label; 60 private static Logger logger = Logger.getLogger("com.horstmann.corejava"); 61 62 public ImageViewerFrame() 63 { 64 logger.entering("ImageViewerFrame", "<init>"); 65 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 66 67 // set up menu bar 68 var menuBar = new JMenuBar(); 69 setJMenuBar(menuBar); 70 71 var menu = new JMenu("File"); 72 menuBar.add(menu); 73 74 var openItem = new JMenuItem("Open"); 75 menu.add(openItem); 76 openItem.addActionListener(new FileOpenListener()); 77 78 var exitItem = new JMenuItem("Exit"); 79 menu.add(exitItem); 80 exitItem.addActionListener(new ActionListener() 81 { 82 public void actionPerformed(ActionEvent event) 83 { 84 logger.fine("Exiting."); 85 System.exit(0); 86 } 87 }); 88 89 // use a label to display the images 90 label = new JLabel(); 91 add(label); 92 logger.exiting("ImageViewerFrame", "<init>"); 93 } 94 95 private class FileOpenListener implements ActionListener 96 { 97 public void actionPerformed(ActionEvent event) 98 { 99 logger.entering("ImageViewerFrame.FileOpenListener", "actionPerformed", event); 100 101 // set up file chooser 102 var chooser = new JFileChooser(); 103 chooser.setCurrentDirectory(new File(".")); 104 105 // accept all files ending with .gif 106 chooser.setFileFilter(new javax.swing.filechooser.FileFilter() 107 { 108 public boolean accept(File f) 109 { 110 return f.getName().toLowerCase().endsWith(".gif") || f.isDirectory(); 111 } 112 113 public String getDescription() 114 { 115 return "GIF Images"; 116 } 117 }); 118 119 // show file chooser dialog 120 int r = chooser.showOpenDialog(ImageViewerFrame.this); 121 122 // if image file accepted, set it as icon of the label 123 if (r == JFileChooser.APPROVE_OPTION) 124 { 125 String name = chooser.getSelectedFile().getPath(); 126 logger.log(Level.FINE, "Reading file {0}", name); 127 label.setIcon(new ImageIcon(name)); 128 } 129 else logger.fine("File open dialog canceled."); 130 logger.exiting("ImageViewerFrame.FileOpenListener", "actionPerformed"); 131 } 132 } 133 } 134 135 /** 136 * A handler for displaying log records in a window. 137 */ 138 class WindowHandler extends StreamHandler 139 { 140 private JFrame frame; 141 142 public WindowHandler() 143 { 144 frame = new JFrame(); 145 var output = new JTextArea(); 146 output.setEditable(false); 147 frame.setSize(200, 200); 148 frame.add(new JScrollPane(output)); 149 frame.setFocusableWindowState(false); 150 frame.setVisible(true); 151 setOutputStream(new OutputStream() 152 { 153 public void write(int b) 154 { 155 } // not called 156 157 public void write(byte[] b, int off, int len) 158 { 159 output.append(new String(b, off, len)); 160 } 161 }); 162 } 163 164 public void publish(LogRecord record) 165 { 166 if (!frame.isVisible()) return; 167 super.publish(record); 168 flush(); 169 } 170 }
運行結果以下:
實驗程序3:
1)用JDK命令調試運行教材298頁-300頁程序7-2,結合程序運行結果理解程序;
2) 按課件66-77內容練習並掌握Elipse的經常使用調試技術。
①條件斷點 –在Eclipse Java 編輯區的行頭雙擊就會獲得一個斷點, 代碼會運行到此處時中止。
–條件斷點,顧名思義就是一個有必定條件的斷點,只有知足了用戶設置的條件,代碼纔會在運行到斷點處時中止。
–在斷點處點擊鼠標右鍵,選擇後一個「Breakpoint Properties」.
添加斷點
點擊「Breakpoint Properties」以後:
②變量斷點–斷點不只能打在語句上,變量也能夠接受斷點:
上圖就是一個變量的打的斷點,在變量的值初 始化,或是變量值改變時能夠中止,固然變量 斷點上也是能夠加條件的,和上面的介紹的條 件斷點的設置是同樣的。
③方法斷點 –方法斷點就是將斷點打在方法的入口處:
–方法斷點的特別之處在於它能夠打在JDK的源碼裏,因爲JDK在編譯時去掉了調試信息,因此普通斷點是不能打到裏面的,可是方法斷點卻能夠,能夠經過這種方法查看方法的調用棧。
④異常斷點
–常常碰見一些異常,而後程序就退出來了,要找到異常發生的地方就比較難了,還好能夠打一個異常斷點。
–上圖中咱們增長了一個NullPointException的異常斷點,當異常發生時,代碼會停在異常發生處,定 位問題時應該比較有幫助。
⑤從新調試
–這種調試的回退不是萬能的,只能在當前線程的棧幀中回退,也就說最多隻能退回到當前線程的調用的開始處。
–回退時,請在須要回退的線程方法上點右鍵,選擇 「Drop to Frame」。
實驗總結:本週學習了第七章的知識,異常有致命性異常和非致命性異常,後者,能夠經過程序員的相關操做進行處理,經過學習知道利用try子句捕獲異常代碼的範圍,它的執行過程當中生成異常對象並拋出異常,不論代碼塊中是否有異常,finally塊中的語句都執行;驗證了積極處理方式和消極處理方式,分別用throws子句和try子句;總而言之理論知識能夠經過課件以及基本理解了相關概念,可是本身實驗的動手能力不斷地提升。在本次自主編程實驗中,雖然那程序能夠運行,可是那test.txt文本沒有出現,以爲本身在這方面仍是不太熟悉,有欠缺,但課後本身會找時間將這部份內容再從新學習。
獲獎感言:
很榮幸能得到這一次的微軟小黃衫獎勵,這既是對我學習確定也是我更加努力學習的動力。我知道我能得到此次獎勵和老師上課時的敦敦教誨,助教的悉心指導,同窗們的熱心幫助分不開的,很是感謝你們,從此的學習生活中我必定會更加努力,不辜負你們對個人支持。