24 例外處理(Exception handling)-2
[24-1內建例外處理類別的訊息]
[getMessage()方法]
內建例外處理類別的簡單訊息可經由個別例外類別的getMessage()方法取得。getMessage()方法只取得訊息,可以System.out.println等顯示。
[例]
public class GetMsg1{
public static void main(String[] args){
try{
int[] box = {10,20,30};
int a = box[1];
System.out.println("a的整數值為"+a);
int b = box[3];
System.out.println("b的整數值為"+b);
}
catch(IndexOutOfBoundsException e1){
System.out.println("e1例外訊息:"+e1.getMessage());
}
catch(Exception e2){
System.out.println("e2例外訊息:"+e2. getMessage());
}
finally{
System.out.println("GetMsg1程式結束");
}
}
}
執行結果:C:\js>java GetMsg1
a的整數值為20
e1例外訊息:3
GetMsg1程式結束
由上述e1.getMssage方法顯示的訊息僅為"3",即指造成錯誤之陣列指標超過0、1、2為3,太過於簡略。
[printStackTrace(System.out)方法]
內建例外處理類別的詳細訊息可經由個別例外類別的printStackTrace(System.out)方法取得。printStackTrace(System.out)方法可直接顯示,不須使用System.out.println等。
[例]
public class GetMsg2{
public static void main(String[] args){
try{
int[] box = {10,20,30};
int a = box[1];
System.out.println("GetMsg2之a的整數值為"+a);
int b = box[3];
System.out.println("GetMsg2之b的整數值為"+b);
}
catch(IndexOutOfBoundsException e1){
e1.printStackTrace(System.out));
}
catch(Exception e2){
e2.printStackTrace(System.out));
}
finally{
System.out.println("GetMsg2程式結束");
}
}
}
執行結果:C:\js>java GetMsg2
GetMsg2之a的整數值為20
java.lang.ArrayIndexOutOfBoundsException: 3
at GetMsg2.main(GetMsg2.java:7)
GetMsg2程式結束
printStackTrace(System.out)方法可顯示較詳細、可讀之訊息。
[24-2自訂例外處理類別的訊息]
經由throw可自訂例外訊息,即透過內建例外處理類別自訂顯示訊息。
[例]未指定訊息
import java.io.*;
import java.lang.*;
class MainException6 {
public static void main(String args[]) {
try{
int m=0, n=0 ;
if(n == 0){
ArithmeticException e = new ArithmeticException ();
throw e;
//或合併為 throw new ArithmeticException ()
}
m = 100/n;
}
catch(ArithmeticException e) {
System.out.println(e.getMessage());
}
}
}
執行結果:C:\js>java MainException6
null
因未指定訊息,尚未發生例外前由throw丟出例外,故其訊息為null。
[例]給定訊息
import java.io.*;
import java.lang.*;
class MainException7 {
public static void main(String args[]) {
try{
int m=0, n=0 ;
if(n == 0){
ArithmeticException e = new ArithmeticException ("錯誤:除數為0!");
throw e;
//或合併為 throw new ArithmeticException ("錯誤:除數為0!")
}
m = 100/n;
}
catch(ArithmeticException e) {
System.out.println(e.getMessage());
}
}
}
執行結果:C:\js>java MainException7
錯誤:除數為0!
[24-3自訂例外處理類別]
經由內建處理類別的繼承,可自訂例外處理類別,也可以自訂顯示例外訊息。
[24-3-1自訂例外處理類別及固定格式訊息]
固定格式的自訂訊息,於繼承時確立訊息。
import java.lang.*;
class MyException extends ArithmeticException { //自訂例外處理類別
MyException() {
super("MyException:除數為0");
//執行父類別建構式並設定例外訊息
}
class MainException8 {
public static void main(String args[]) {
try{
int m=0, n=0;
if(n == 0){
MyException e = new MyException ();
throw e;
}
m = 100/n;
}
catch(MyException e) {
System.out.println(e.getMessage());
}
}
}
執行結果:C:\js>java MainException8
MyException:除數為0
[24-3-2自訂例外處理類別及彈性格式訊息]
自訂訊息,於建立物件時指定。
import java.lang.*;
class FlexException extends ArithmeticException {
FlexException(String msg) { //建立物件時可指定訊息
super(msg);
}
}
class MainException9 {
public static void main(String args[]) {
try{
int m=0, n=0;
if(n == 0) throw new FlexException("彈性格式:除數為0");
m = 100/n;
}
catch(FlexException e) {
System.out.println(e.getMessage());
}
}
}
執行結果:C:\js>java MainException9
彈性格式:除數為0
[24-4例外處理程式碼的所在]
系統或自行(throw)拋出的例外要在那一個類別的那一個方法內處理?
*由拋出例外的方法捕捉處理。
*由拋出例外的方法上層方法(即呼叫者,可為同類別或他類別)捕捉處理。
*如拋出例外的方法之上層方法沒捕捉處理,可再由上上層捕捉處理,如果一直往上都沒有捕捉處理,最後由JVM處理及拋出訊息。
[24-4-1同一方法內]
class Exception11{
public static void main(String[] args){
Exception21 E21 = new Exception21();
E21.emethod211(); }
}
class Exception21{
public void emethod211(){
emethod212(); }
public void emethod212(){
try{ int a=10, b=0, c=0;
c=a/b; }
catch( ArithmeticException e){
System.out.println(e.getMessage()); }
}
}
執行結果:C:\js>java Exception11
/ by zero
[24-4-2上層(同類別他方法)]
class Exception12{
public static void main(String[] args){
Exception22 E22 = new Exception22();
E22.emethod221(); }
}
class Exception22{
public void emethod221(){
try{ emethod222(); }
catch( ArithmeticException e){
System.out.println(e.getMessage()); }
}
public void emethod222(){
int a=10, b=0, c=0;
c=a/b; }
}
執行結果:C:\js>java Exception12
/ by zero
[24-4-3上層(他類別)]
class Exception13{
public static void main(String[] args){
Exception23 E23 = new Exception23();
try{ E23.emethod231(); }
catch( ArithmeticException e){
System.out.println(e.getMessage()); }
}
}
class Exception23{
public void emethod231(){
emethod232(); }
public void emethod232(){
int a=10, b=0, c=0;
c=a/b; }
}
執行結果:C:\js>java Exception13
/ by zero
[24-4-4 JVM(無try/catch)]
class Exception14{
public static void main(String[] args){
Exception24 E24 = new Exception24();
E24.emethod241(); }
}
class Exception24{
public void emethod241(){
emethod242(); }
public void emethod242(){
int a=10, b=0, c=0;
c=a/b; }
}
執行結果:C:\js>java Exception14
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Exception24.emethod242(Exception14.java:11)
at Exception24.emethod241(Exception14.java:8)
at Exception14.main(Exception14.java:4)
*JVM拋出之訊息和由getMessage()顯示之訊息不同。
[24-5由例外類別繼承體系的那一個類別捕捉處理]
Java系統內建例外處理類別繼承體系之父子類別關係如下表例,程式catch述句可撰寫相對應之類別來捕捉異常。
Java系統內建例外處理類別之父子類別關係表
T h r o w a b l e ( 根 類 別 ) |
Error (處不處理 皆可) |
VirtualMachineError |
StackOverflowError |
|
OutOfMemoryError |
||||
AssertionError |
||||
LinkageError |
ExceptionInInitializerError |
|||
NoClassDefFoundError |
||||
E x c e p t i o n |
Unchecked Exception (處不處理 皆可) |
RuntimeException |
ArithmeticException |
|
NullPointerException |
||||
IllegalStateException |
||||
IndexOutOfBoundsException |
||||
ClassCastException |
||||
IllegalArgumentException |
||||
Checked Exception (須處理) |
IOException |
EOFException |
||
FileNotFoundException |
||||
ClassNotFoundException |
||||
SQLException |
||||
InterruptedException |
[24-5-1由例外類別本身捕捉處理]
例:設有一陣列包含5個元素,並由命令列輸入欲顯示內容之陣列元素。如命令列輸入之陣列元素超出陣列範圍,則顯示“陣列元素n超出範圍!”及“程式結束。”,如輸入之陣列元素在陣列範圍內,則顯示“陣列元素n = x!”及“程式結束。”,其中n為由1開始之陣列元素次序值,x為第n個陣列元素內容。
import java.io.*;
public class Exception31 {
public static void main(String args[]) {
if (args.length != 1) {
System.out.println("請輸入一個陣列元素次序值");
System.exit(1);
}
int n = Integer.parseInt(args[0]);
try {
int x[] = {3,6,9,12,15};
System.out.println("陣列元素" + n + " = " + x[n-1] + "!");
}
catch (ArrayIndexOutOfBoundsException ae) {
System.out.println("Exception31陣列元素" + n + "超出範圍!");
}
finally {
System.out.println("程式結束。");
}
}
}
執行結果:
C:\js>java Exception31 5
陣列元素5 = 15!
程式結束。
C:\js>java Exception31 6
Exception31陣列元素6超出範圍!
程式結束。
C:\js>java Exception31
請輸入一個陣列元素次序值
[24-5-2由例外類別的父類別、祖父類別捕捉處理]
上例由其上一層例外處理類別" IndexOutOfBoundsException"來接收例外之範例如下:
import java.io.*;
public class Exception32 {
public static void main(String args[]) {
if (args.length != 1) {
System.out.println("請輸入一個陣列元素次序值");
System.exit(1);
}
int n = Integer.parseInt(args[0]);
try {
int x[] = {3,6,9,12,15};
System.out.println("陣列元素" + n + " = " + x[n-1] + "!");
}
catch (IndexOutOfBoundsException ie) {
System.out.println("Exception32陣列元素" + n + "超出範圍!");
}
finally {
System.out.println("程式結束。");
}
}
}
執行結果:C:\js>java Exception32 7
Exception32陣列元素7超出範圍!
程式結束。
[24-5-3由繼承體系多個例外類別捕捉處理]
可以多個catch捕捉繼承體系上相對應之例外及錯誤:
下例以"RuntimeException"、"IndexOutOfBoundsException" 、 "ArrayIndexOutOfBoundsException" 捕捉,但實際為"ArithmeticException",本例只能由其父類別"RuntimeException"捕捉。
class Exception33{
public static void main(String[] args){
try{ int a=10, b=0, c=0;
c=a/b; }
catch(ArrayIndexOutOfBoundsException e1){
System.out.println("e1:" + e1.getMessage()); }
catch(IndexOutOfBoundsException e2){
System.out.println("e2:" + e2.getMessage()); }
catch(RuntimeException e3){
System.out.println("e3:" + e3.getMessage()); }
}
}
執行結果:C:\js>java Exception33
e3:/ by zero
[由"Exception"例外類別處理]
如果沒有辦法知曉何種例外時,則可以例外類別(非錯誤類別)的最上位Exception總括處理,並以其方法(get.Message())取得訊息,如下例:
class Exception34{
public static void main(String[] args){
try{ int a=10, b=0, c=0;
c=a/b; }
catch(Exception ex){
System.out.println("ex:" + ex.getMessage());
ex.printStackTrace(System.out); }
}
}
執行結果:C:\js>java Exception34
ex:/ by zero
java.lang.ArithmeticException: / by zero
at Exception34.main(Exception34.java:4)
留言列表