章節六、1-異常---編譯時會被檢測的
一、異常其實就是將問題封裝成物件並拋給呼叫者,異常的出現是為了提高程式的健壯性而將問題描述出來。
java分兩個時期,一個叫編譯時期,一個叫執行時期,編譯時期就是說檢查語法錯誤,也就是原始碼有沒有寫錯,如果原始碼沒寫錯,生成的.class檔案在執行時期出錯,這些情況就叫異常。
二、新建兩個類,類名為ExceptionsDemo和Account,使用丟擲異常的方式來處理異常。
1、在Account這個類中寫一個“取錢”的功能
package introduction8; /*匯入包為 * import java.sql.Connection; * 將Connection改為*後,這樣就能一次性將sql這個包中的所有類*/ import java.sql.Connection; import java.sql.DriverManager; public class Accout { /* 在取錢之前,程式要訪問資料庫,提供賬號資訊、餘額進行運算,然後判斷能不能取出錢, * 因此需要先寫一個能丟擲異常,顯示異常的功能, * 因為要建立一個數據庫連結,使用mysql為例 */ public Connection getConn() { //Connection為引用型變數,預設值為空,用於與特定資料庫進行連線, //他是一個介面,我們需要用到Connection連結 Connection conn = null; //定義連線資料庫需要用到的引數 /*因為使用mysql資料庫,所以使用jdbc,表示java資料庫連線, * 是一種用於執行sql語句的java api,jdbc是java資料庫的標準, * 提供了一種讓java程式連線到資料庫的機制,如果要使用jdbc連線到資料庫, * 必須要使用jdbc驅動程式。 * (本機還未安裝資料庫,此處目的是為了演示異常,所以執行時會報異常) */ String url = "jdbc:mysql://localhost:3306/"; String user= "user"; String password = "code"; //Connection是一個靜態方法,所以能夠直接呼叫,建立資料庫連線 conn = DriverManager.getConnection(url, user, password); return conn; } public void withdraw(int money) { } }
在eclipse中conn = DriverManager.getConnection(url, user, password);程式碼報錯,
這裡會報異常是因為Connection介面中有檢查異常的機制,所以此處報出了sql異常
2、因為在getConn方法中有異常所以,在這個方法上要有throws宣告出來,不然編譯會失敗,宣告的目的是為了讓呼叫這個getConn方法的人去處理,如果呼叫者也不處理的話,編譯還是會失敗的,在eclipse中滑鼠移動到報錯的程式碼上,會給出上圖中兩次解決方式(throws丟擲異常,try/catch捕獲並處理異常),這裡選擇第一種,直接丟擲異常,讓呼叫者自己解決。
3、選擇丟擲異常後在其它方法中呼叫,直接呼叫時會報異常,這就是前面提到的,如果呼叫者不處理的話,編譯還是會報錯。然後繼續給呼叫的方法宣告丟擲異常。
4、在ExceptionsDemo類中呼叫
package introduction8; /* * 執行時會發生的問題分兩類: * 1、exception異常: * 這種異常是可處理的,java虛擬機器是用來解釋並執行java程式的應用軟體, * 這種是異常直接從java虛擬機發生的,是java虛擬機器在執行過程中發生的問題, * 並告訴給使用者,對異常可以進行鍼對性處理。 * exception異常分兩種: * a、編譯時檢查的異常,先檢查語法的問題,語法都對的情況下再檢查語法的安全問題。 * 對於編譯時被檢查的異常,功能如果有問題,當功能中又未宣告的話,就會報錯並且不會讓程式執行通過。 * b、執行時異常,執行時異常編譯器是不檢查 * 如果程式碼中有零做為除數,編譯時是不會檢查該異常的,執行時才會報錯,也就是說除數為零,程式碼的語法 * 和功能是沒有問題的,只不過傳的引數有問題。另外就是數值角標越界的情況,例如數值的長度為3, * 角標就是0、1、2這3個數,想訪問角標為3的元素,編譯時不會報錯,執行時報錯,因為3這個元素根本不存在。 * 2、Error錯誤: * Error發生是不處理的,error是由系統底層發生的,底層告訴了java虛擬機器的,java虛擬機器告訴使用者, * 例如記憶體溢位,一旦發生error了,必須修改程式碼,對異常本身不做針對性處理。 */ //因為用的IDE整合開發環境,都是可以檢查編譯時異常,異常的部分會先紅色波浪線和紅叉圖示 public class ExceptionsDemo { public static void main(String[] args) { Accout acc = new Accout(); acc.withdraw(100); } }
呼叫後傳參仍然報異常:
繼續選擇宣告異常,點選執行,控制檯提示異常
三、使用try/catch捕獲異常
package introduction8; import java.sql.SQLException; /* * 執行時會發生的問題分兩類: * 1、exception異常: * 這種異常是可處理的,java虛擬機器是用來解釋並執行java程式的應用軟體, * 這種是異常直接從java虛擬機發生的,是java虛擬機器在執行過程中發生的問題, * 並告訴給使用者,對異常可以進行鍼對性處理。 * exception異常分兩種: * a、編譯時檢查的異常,先檢查語法的問題,語法都對的情況下再檢查語法的安全問題。 * 對於編譯時被檢查的異常,功能如果有問題,當功能中又未宣告的話,就會報錯並且不會讓程式執行通過。 * b、執行時異常,執行時異常編譯器是不檢查 * 如果程式碼中有零做為除數,編譯時是不會檢查該異常的,執行時才會報錯,也就是說除數為零,程式碼的語法 * 和功能是沒有問題的,只不過傳的引數有問題。另外就是數值角標越界的情況,例如數值的長度為3, * 角標就是0、1、2這3個數,想訪問角標為3的元素,編譯時不會報錯,執行時報錯,因為3這個元素根本不存在。 * 2、Error錯誤: * Error發生是不處理的,error是由系統底層發生的,底層告訴了java虛擬機器的,java虛擬機器告訴使用者, * 例如記憶體溢位,一旦發生error了,必須修改程式碼,對異常本身不做針對性處理。 */ //因為用的IDE整合開發環境,都是可以檢查編譯時異常,異常的部分會先紅色波浪線和紅叉圖示 public class ExceptionsDemo { public static void main(String[] args){ Accout acc = new Accout(); try { /*把可能出現異常的程式碼反正try/catch這個大括號裡面, * 如果try裡面的語句有異常,就回去執行catch裡面的語句 */ acc.withdraw(100); } catch (SQLException e) { //將異常資訊封裝成物件並列印 e.printStackTrace(); } } }
執行後的結果:
如果想自定義只打印錯誤資訊:
四、catch不能離開try單獨使用。
try語句可以沒有catch,當try語句不能單獨執行,如果沒有catch就必須要與finally一起使用。
五、finally{}放在finally中的語句一定會被執行
六、try是如何工作的?
1、在try中新增如下兩行程式碼,以便於我們能直觀的看到try是如何執行的
結果:
直接跳過列印“執行withdraw”這條命令語句,執行catch和finally中的語句,這是因為try中有異常
2、註釋未處理前報異常的程式碼
點選執行:
跳過了catch中的語句,只執行了try和finally中的語句,這是因為try中沒有異常
7、try與finally一起使用,沒有catch
這是在不一定要處理異常,但是有資源需要釋放的情況下使用。
註釋掉catch,然後執行
執行成功:
finally語句塊中可以放釋放資源的語句,例如斷開資料庫連線,有時候程式出現異常,資源是來不及釋放的,而如果把資源放在finally中,就可以得到釋放,因為finally中的語句是肯定會被執行的。