java程序经过编译后会产生byte code_学习廖雪峰的JAVA教程---异常处理(Java的异常)...
在計算機程序運行的過程中,總是會出現各種各樣的錯誤。
有一些錯誤是用戶造成的,比如,希望用戶輸入一個int類型的年齡,但是用戶的輸入是abc:
// 假設用戶輸入了abc:String s = "abc";int n = Integer.parseInt(s); // NumberFormatException!程序想要讀寫某個文件的內容,但是用戶已經把它刪除了:
// 用戶刪除了該文件:String t = readFile("C:abc.txt"); // FileNotFoundException!還有一些錯誤是隨機出現,并且永遠不可能避免的。比如:
- 網絡突然斷了,連接不到遠程服務器;
- 內存耗盡,程序崩潰了;
- 用戶點“打印”,但根本沒有打印機;
- ……
所以,一個健壯的程序必須處理各種各樣的錯誤。
所謂錯誤,就是程序調用某個函數的時候,如果失敗了,就表示出錯。
調用方如何獲知調用失敗的信息?有兩種方法:
方法一:約定返回錯誤碼。
例如,處理一個文件,如果返回0,表示成功,返回其他整數,表示約定的錯誤碼:
int code = processFile("C:est.txt");if (code == 0) { // ok:} else { // error: switch (code) { case 1: // file not found: case 2: // no read permission: default: // unknown error: }}因為使用int類型的錯誤碼,想要處理就非常麻煩。這種方式常見于底層C函數。
方法二:在語言層面上提供一個異常處理機制。
Java內置了一套異常處理機制,總是使用異常來表示錯誤。
異常是一種class,因此它本身帶有類型信息。異常可以在任何地方拋出,但只需要在上層捕獲,這樣就和方法調用分離了:
try { String s = processFile(“C:est.txt”); // ok:} catch (FileNotFoundException e) { // file not found:} catch (SecurityException e) { // no read permission:} catch (IOException e) { // io error:} catch (Exception e) { // other error:}因為Java的異常是class,它的繼承關系如下:
從繼承關系可知:Throwable是異常體系的根,它繼承自Object。Throwable有兩個體系:Error和Exception,Error表示嚴重的錯誤,程序對此一般無能為力,例如:
- OutOfMemoryError:內存耗盡
- NoClassDefFoundError:無法加載某個Class
- StackOverflowError:棧溢出
而Exception則是運行時的錯誤,它可以被捕獲并處理。
某些異常是應用程序邏輯處理的一部分,應該捕獲并處理。例如:
- NumberFormatException:數值類型的格式錯誤
- FileNotFoundException:未找到文件
- SocketException:讀取網絡失敗
還有一些異常是程序邏輯編寫不對造成的,應該修復程序本身。例如:
- NullPointerException:對某個null的對象調用方法或字段
- IndexOutOfBoundsException:數組索引越界
Exception又分為兩大類:
Java規定:
- 必須捕獲的異常,包括Exception及其子類,但不包括RuntimeException及其子類,這種類型的異常稱為Checked Exception。
- 不需要捕獲的異常,包括Error及其子類,RuntimeException及其子類。
捕獲異常
捕獲異常使用try...catch語句,把可能發生異常的代碼放到try {...}中,然后使用catch捕獲對應的Exception及其子類:
// try...catchimport java.io.UnsupportedEncodingException;import java.util.Arrays;public class Main { public static void main(String[] args) { byte[] bs = toGBK("中文"); System.out.println(Arrays.toString(bs)); } static byte[] toGBK(String s) { try { // 用指定編碼轉換String為byte[]: return s.getBytes("GBK"); } catch (UnsupportedEncodingException e) { // 如果系統不支持GBK編碼,會捕獲到UnsupportedEncodingException: System.out.println(e); // 打印異常信息 return s.getBytes(); // 嘗試使用用默認編碼 } }}(上面的執行為什么出現一個數組呢?)
如果我們不捕獲UnsupportedEncodingException,會出現編譯失敗的問題:
// try...catchimport java.io.UnsupportedEncodingException;import java.util.Arrays;public class Main { public static void main(String[] args) { byte[] bs = toGBK("中文"); System.out.println(Arrays.toString(bs)); } static byte[] toGBK(String s) { return s.getBytes("GBK"); }}以上代碼運行結果:Main.java:11: 錯誤: 未報告的異常錯誤UnsupportedEncodingException; 必須對其進行捕獲或聲明以便拋出
return s.getBytes("GBK");
^
1 個錯誤
錯誤: 編譯失敗
編譯器會報錯,錯誤信息類似:unreported exception UnsupportedEncodingException; must be caught or declared to be thrown,并且準確地指出需要捕獲的語句是return s.getBytes("GBK");。意思是說,像UnsupportedEncodingException這樣的Checked Exception,必須被捕獲。
這是因為String.getBytes(String)方法定義是:
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { ...}在方法定義的時候,使用throws Xxx表示該方法可能拋出的異常類型。調用方在調用的時候,必須強制捕獲這些異常,否則編譯器會報錯。
在toGBK()方法中,因為調用了String.getBytes(String)方法,就必須捕獲UnsupportedEncodingException。我們也可以不捕獲它,而是在方法定義處用throws表示toGBK()方法可能會拋出UnsupportedEncodingException,就可以讓toGBK()方法通過編譯器檢查:
// try...catchimport java.io.UnsupportedEncodingException;import java.util.Arrays;public class Main { public static void main(String[] args) { byte[] bs = toGBK("中文"); System.out.println(Arrays.toString(bs)); } static byte[] toGBK(String s) throws UnsupportedEncodingException { return s.getBytes("GBK"); }}以上執行結果:Main.java:6: 錯誤: 未報告的異常錯誤UnsupportedEncodingException; 必須對其進行捕獲或聲明以便拋出
byte[] bs = toGBK("中文");
^
1 個錯誤
錯誤: 編譯失敗
上述代碼仍然會得到編譯錯誤,但這一次,編譯器提示的不是調用return s.getBytes("GBK");的問題,而是byte[] bs = toGBK("中文");。因為在main()方法中,調用toGBK(),沒有捕獲它聲明的可能拋出的UnsupportedEncodingException。
修復方法是在main()方法中捕獲異常并處理:
// try...catchimport java.io.UnsupportedEncodingException;import java.util.Arrays;public class Main { public static void main(String[] args) { try { byte[] bs = toGBK("中文"); System.out.println(Arrays.toString(bs)); } catch (UnsupportedEncodingException e) { System.out.println(e); } } static byte[] toGBK(String s) throws UnsupportedEncodingException {//讓main去捕獲 // 用指定編碼轉換String為byte[]: return s.getBytes("GBK"); }}(從兩次執行的結果來看,如果函數內部有方法在定義時候使用throws,外部函數要么在內部使用try ..catch對其進行捕獲,要么在定義的時候要throw表示可能會拋出unsupportedEncodingException ,這樣才能通過編譯。看來這也是java語言為什么健壯的保證,最好還是使用try catch)
可見,只要是方法聲明的Checked Exception,不在調用層捕獲,也必須在更高的調用層捕獲。所有未捕獲的異常,最終也必須在main()方法中捕獲,不會出現漏寫try的情況。這是由編譯器保證的。main()方法也是最后捕獲Exception的機會。
如果是測試代碼,上面的寫法就略顯麻煩。如果不想寫任何try代碼,可以直接把main()方法定義為throws Exception:
// try...catchimport java.io.UnsupportedEncodingException;import java.util.Arrays;public class Main { public static void main(String[] args) throws Exception {//也不想再main里trycatch可以選擇這樣throws Exception byte[] bs = toGBK("中文"); System.out.println(Arrays.toString(bs)); } static byte[] toGBK(String s) throws UnsupportedEncodingException { // 用指定編碼轉換String為byte[]: return s.getBytes("GBK"); }}因為main()方法聲明了可能拋出Exception,也就聲明了可能拋出所有的Exception,因此在內部就無需捕獲了。代價就是一旦發生異常,程序會立刻退出。還有一些童鞋喜歡在toGBK()內部“消化”異常:
static byte[] toGBK(String s) { try { return s.getBytes("GBK"); } catch (UnsupportedEncodingException e) { // 什么也不干 } return null;這種捕獲后不處理的方式是非常不好的,即使真的什么也做不了,也要先把異常記錄下來:
static byte[] toGBK(String s) { try { return s.getBytes("GBK"); } catch (UnsupportedEncodingException e) { // 先記下來再說: e.printStackTrace(); } return null;所有異常都可以調用printStackTrace()方法打印異常棧,這是一個簡單有用的快速打印異常的方法。
小結
Java使用異常來表示錯誤,并通過try ... catch捕獲異常;
Java的異常是class,并且從Throwable繼承;
Error是無需捕獲的嚴重錯誤,Exception是應該捕獲的可處理的錯誤;
RuntimeException無需強制捕獲,非RuntimeException(Checked Exception)需強制捕獲,或者用throws聲明;
不推薦捕獲了異常但不進行任何處理。
【關鍵:
必須捕獲的異常,包括Exception及其子類,但不包括RuntimeException及其子類,這種類型的異常稱為Checked Exception。
不需要捕獲的異常,包括Error及其子類,RuntimeException及其子類。
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
...
}
】
總結
以上是生活随笔為你收集整理的java程序经过编译后会产生byte code_学习廖雪峰的JAVA教程---异常处理(Java的异常)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu c mysql_Ubunt
- 下一篇: java字符匹配,Java:匹配字符串中