java程序经过编译后会产生byte code_学习廖雪峰的JAVA教程---异常处理(Java的异常)...
在計(jì)算機(jī)程序運(yùn)行的過(guò)程中,總是會(huì)出現(xiàn)各種各樣的錯(cuò)誤。
有一些錯(cuò)誤是用戶(hù)造成的,比如,希望用戶(hù)輸入一個(gè)int類(lèi)型的年齡,但是用戶(hù)的輸入是abc:
// 假設(shè)用戶(hù)輸入了abc:String s = "abc";int n = Integer.parseInt(s); // NumberFormatException!程序想要讀寫(xiě)某個(gè)文件的內(nèi)容,但是用戶(hù)已經(jīng)把它刪除了:
// 用戶(hù)刪除了該文件:String t = readFile("C:abc.txt"); // FileNotFoundException!還有一些錯(cuò)誤是隨機(jī)出現(xiàn),并且永遠(yuǎn)不可能避免的。比如:
- 網(wǎng)絡(luò)突然斷了,連接不到遠(yuǎn)程服務(wù)器;
- 內(nèi)存耗盡,程序崩潰了;
- 用戶(hù)點(diǎn)“打印”,但根本沒(méi)有打印機(jī);
- ……
所以,一個(gè)健壯的程序必須處理各種各樣的錯(cuò)誤。
所謂錯(cuò)誤,就是程序調(diào)用某個(gè)函數(shù)的時(shí)候,如果失敗了,就表示出錯(cuò)。
調(diào)用方如何獲知調(diào)用失敗的信息?有兩種方法:
方法一:約定返回錯(cuò)誤碼。
例如,處理一個(gè)文件,如果返回0,表示成功,返回其他整數(shù),表示約定的錯(cuò)誤碼:
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: }}因?yàn)槭褂胕nt類(lèi)型的錯(cuò)誤碼,想要處理就非常麻煩。這種方式常見(jiàn)于底層C函數(shù)。
方法二:在語(yǔ)言層面上提供一個(gè)異常處理機(jī)制。
Java內(nèi)置了一套異常處理機(jī)制,總是使用異常來(lái)表示錯(cuò)誤。
異常是一種class,因此它本身帶有類(lèi)型信息。異常可以在任何地方拋出,但只需要在上層捕獲,這樣就和方法調(diào)用分離了:
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:}因?yàn)镴ava的異常是class,它的繼承關(guān)系如下:
從繼承關(guān)系可知:Throwable是異常體系的根,它繼承自O(shè)bject。Throwable有兩個(gè)體系:Error和Exception,Error表示嚴(yán)重的錯(cuò)誤,程序?qū)Υ艘话銦o(wú)能為力,例如:
- OutOfMemoryError:內(nèi)存耗盡
- NoClassDefFoundError:無(wú)法加載某個(gè)Class
- StackOverflowError:棧溢出
而Exception則是運(yùn)行時(shí)的錯(cuò)誤,它可以被捕獲并處理。
某些異常是應(yīng)用程序邏輯處理的一部分,應(yīng)該捕獲并處理。例如:
- NumberFormatException:數(shù)值類(lèi)型的格式錯(cuò)誤
- FileNotFoundException:未找到文件
- SocketException:讀取網(wǎng)絡(luò)失敗
還有一些異常是程序邏輯編寫(xiě)不對(duì)造成的,應(yīng)該修復(fù)程序本身。例如:
- NullPointerException:對(duì)某個(gè)null的對(duì)象調(diào)用方法或字段
- IndexOutOfBoundsException:數(shù)組索引越界
Exception又分為兩大類(lèi):
Java規(guī)定:
- 必須捕獲的異常,包括Exception及其子類(lèi),但不包括RuntimeException及其子類(lèi),這種類(lèi)型的異常稱(chēng)為Checked Exception。
- 不需要捕獲的異常,包括Error及其子類(lèi),RuntimeException及其子類(lèi)。
捕獲異常
捕獲異常使用try...catch語(yǔ)句,把可能發(fā)生異常的代碼放到try {...}中,然后使用catch捕獲對(duì)應(yīng)的Exception及其子類(lèi):
// 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 { // 用指定編碼轉(zhuǎn)換String為byte[]: return s.getBytes("GBK"); } catch (UnsupportedEncodingException e) { // 如果系統(tǒng)不支持GBK編碼,會(huì)捕獲到UnsupportedEncodingException: System.out.println(e); // 打印異常信息 return s.getBytes(); // 嘗試使用用默認(rèn)編碼 } }}(上面的執(zhí)行為什么出現(xiàn)一個(gè)數(shù)組呢?)
如果我們不捕獲UnsupportedEncodingException,會(huì)出現(xiàn)編譯失敗的問(wèn)題:
// 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"); }}以上代碼運(yùn)行結(jié)果:Main.java:11: 錯(cuò)誤: 未報(bào)告的異常錯(cuò)誤UnsupportedEncodingException; 必須對(duì)其進(jìn)行捕獲或聲明以便拋出
return s.getBytes("GBK");
^
1 個(gè)錯(cuò)誤
錯(cuò)誤: 編譯失敗
編譯器會(huì)報(bào)錯(cuò),錯(cuò)誤信息類(lèi)似:unreported exception UnsupportedEncodingException; must be caught or declared to be thrown,并且準(zhǔn)確地指出需要捕獲的語(yǔ)句是return s.getBytes("GBK");。意思是說(shuō),像UnsupportedEncodingException這樣的Checked Exception,必須被捕獲。
這是因?yàn)镾tring.getBytes(String)方法定義是:
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { ...}在方法定義的時(shí)候,使用throws Xxx表示該方法可能拋出的異常類(lèi)型。調(diào)用方在調(diào)用的時(shí)候,必須強(qiáng)制捕獲這些異常,否則編譯器會(huì)報(bào)錯(cuò)。
在toGBK()方法中,因?yàn)檎{(diào)用了String.getBytes(String)方法,就必須捕獲UnsupportedEncodingException。我們也可以不捕獲它,而是在方法定義處用throws表示toGBK()方法可能會(huì)拋出UnsupportedEncodingException,就可以讓toGBK()方法通過(guò)編譯器檢查:
// 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"); }}以上執(zhí)行結(jié)果:Main.java:6: 錯(cuò)誤: 未報(bào)告的異常錯(cuò)誤UnsupportedEncodingException; 必須對(duì)其進(jìn)行捕獲或聲明以便拋出
byte[] bs = toGBK("中文");
^
1 個(gè)錯(cuò)誤
錯(cuò)誤: 編譯失敗
上述代碼仍然會(huì)得到編譯錯(cuò)誤,但這一次,編譯器提示的不是調(diào)用return s.getBytes("GBK");的問(wèn)題,而是byte[] bs = toGBK("中文");。因?yàn)樵趍ain()方法中,調(diào)用toGBK(),沒(méi)有捕獲它聲明的可能拋出的UnsupportedEncodingException。
修復(fù)方法是在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去捕獲 // 用指定編碼轉(zhuǎn)換String為byte[]: return s.getBytes("GBK"); }}(從兩次執(zhí)行的結(jié)果來(lái)看,如果函數(shù)內(nèi)部有方法在定義時(shí)候使用throws,外部函數(shù)要么在內(nèi)部使用try ..catch對(duì)其進(jìn)行捕獲,要么在定義的時(shí)候要throw表示可能會(huì)拋出unsupportedEncodingException ,這樣才能通過(guò)編譯。看來(lái)這也是java語(yǔ)言為什么健壯的保證,最好還是使用try catch)
可見(jiàn),只要是方法聲明的Checked Exception,不在調(diào)用層捕獲,也必須在更高的調(diào)用層捕獲。所有未捕獲的異常,最終也必須在main()方法中捕獲,不會(huì)出現(xiàn)漏寫(xiě)try的情況。這是由編譯器保證的。main()方法也是最后捕獲Exception的機(jī)會(huì)。
如果是測(cè)試代碼,上面的寫(xiě)法就略顯麻煩。如果不想寫(xiě)任何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 { // 用指定編碼轉(zhuǎn)換String為byte[]: return s.getBytes("GBK"); }}因?yàn)閙ain()方法聲明了可能拋出Exception,也就聲明了可能拋出所有的Exception,因此在內(nèi)部就無(wú)需捕獲了。代價(jià)就是一旦發(fā)生異常,程序會(huì)立刻退出。還有一些童鞋喜歡在toGBK()內(nèi)部“消化”異常:
static byte[] toGBK(String s) { try { return s.getBytes("GBK"); } catch (UnsupportedEncodingException e) { // 什么也不干 } return null;這種捕獲后不處理的方式是非常不好的,即使真的什么也做不了,也要先把異常記錄下來(lái):
static byte[] toGBK(String s) { try { return s.getBytes("GBK"); } catch (UnsupportedEncodingException e) { // 先記下來(lái)再說(shuō): e.printStackTrace(); } return null;所有異常都可以調(diào)用printStackTrace()方法打印異常棧,這是一個(gè)簡(jiǎn)單有用的快速打印異常的方法。
小結(jié)
Java使用異常來(lái)表示錯(cuò)誤,并通過(guò)try ... catch捕獲異常;
Java的異常是class,并且從Throwable繼承;
Error是無(wú)需捕獲的嚴(yán)重錯(cuò)誤,Exception是應(yīng)該捕獲的可處理的錯(cuò)誤;
RuntimeException無(wú)需強(qiáng)制捕獲,非RuntimeException(Checked Exception)需強(qiáng)制捕獲,或者用throws聲明;
不推薦捕獲了異常但不進(jìn)行任何處理。
【關(guān)鍵:
必須捕獲的異常,包括Exception及其子類(lèi),但不包括RuntimeException及其子類(lèi),這種類(lèi)型的異常稱(chēng)為Checked Exception。
不需要捕獲的異常,包括Error及其子類(lèi),RuntimeException及其子類(lèi)。
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
...
}
】
總結(jié)
以上是生活随笔為你收集整理的java程序经过编译后会产生byte code_学习廖雪峰的JAVA教程---异常处理(Java的异常)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ubuntu c mysql_Ubunt
- 下一篇: gridview的sort_GridVi