1.异常处理
import javax.swing.*; class AboutException { public static void main(String[] a) { int i = 1, j = 0, k; k = i / j; try{ k = i / j; // Causes division-by-zero exception //throw new Exception("Hello.Exception!"); } catch ( ArithmeticException e){ System.out.println("被0除. "+ e.getMessage()); } catch (Exception e){ if (e instanceof ArithmeticException) System.out.println("被0除"); else{ System.out.println(e.getMessage()); } } finally{ JOptionPane.showConfirmDialog(null,"OK"); } }}
使用Java异常处理机制
把可能会发生错误的代码放进try语句块中。当程序检测到出现了一个错误时会抛出一个异常对象。异常处理代码会捕获并处理这个错误。catch语句块中的代码用于处理错误。当异常发生时,程序控制流程由try语句块跳转到catch语句块。不管是否有异常发生,finally语句块中的语句始终保证被执行。如果没有提供合适的异常处理代码,JVM将会结束掉整个应用程序。
Throwable类有两个直接子类:
Exception:出现的问题是可以被捕获的;
Error:系统错误,通常由JVM处理。
可捕获的异常又可以分为两类:
(1)Check异常:直接派生自Exception的异常类,必须被捕获或再次声明抛出
(2)Runtime异常:派生自RuntimeException的异常类。
2.以下代码在运行时不会引发异常,解释原因。
public class ThrowDemo { public static void main(String[] args) { // try { double data = 100 / 0.0; System.out.println("浮点数除以零:" + data); // if(String.valueOf(data).equals("Infinity"))// { // System.out.println("In Here" ); // throw new ArithmeticException("除零异常");// }// } // catch(ArithmeticException e) { // System.out.println(e); // } } }
JVM在具体实现这两个指令时,采用了不同的处理策略,导致两段代码运行时得到不同的结果
3.异常的“多态”特性
可以有多个catch语句块,每个代码块捕获一种异常。在某个try块后有两个不同的catch 块捕获两个相同类型的异常是语法错误。
使用catch语句,只能捕获Exception类及其子类的对象。因此,一个捕获Exception对象的catch语句块可以捕获所有“可捕获”的异常。
将catch(Exception e)放在别的catch块前面会使这些catch块都不执行,因此Java不会编译这个程序。
4.finally”的功用
资源泄露:当一个资源不再被某应用程序使用,但此程序并未向系统声明不再使用此资源时发生这种情况
finally语句块主要用于解决资源泄露问题,它位于catch语句块之后,JVM保证它们一定执行。
注意:finally语句块中也可能发生异常,如果这种情况发生,先前的异常被放弃。
5.阅读以下代码,写出程序运行结果
public class CatchWho { public static void main(String[] args) { try { try { throw new ArrayIndexOutOfBoundsException(); } catch(ArrayIndexOutOfBoundsException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/内层try-catch"); } throw new ArithmeticException(); } catch(ArithmeticException e) { System.out.println("发生ArithmeticException"); } catch(ArrayIndexOutOfBoundsException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/外层try-catch"); } } }
public class CatchWho2 { public static void main(String[] args) { try { try { throw new ArrayIndexOutOfBoundsException(); } catch(ArithmeticException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/内层try-catch"); } throw new ArithmeticException(); } catch(ArithmeticException e) { System.out.println("发生ArithmeticException"); } catch(ArrayIndexOutOfBoundsException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/外层try-catch"); } } }
6. 阅读以下代码,写出程序运行结果
public class EmbededFinally { public static void main(String args[]) { int result; try { System.out.println("in Level 1"); try { System.out.println("in Level 2"); // result=100/0; //Level 2 try { System.out.println("in Level 3"); result=100/0; //Level 3 } catch (Exception e) { System.out.println("Level 3:" + e.getClass().toString()); } finally { System.out.println("In Level 3 finally"); } // result=100/0; //Level 2 } catch (Exception e) { System.out.println("Level 2:" + e.getClass().toString()); } finally { System.out.println("In Level 2 finally"); } // result = 100 / 0; //level 1 } catch (Exception e) { System.out.println("Level 1:" + e.getClass().toString()); } finally {. System.out.println("In Level 1 finally"); } }}
总结:
当有多层嵌套的finally时,异常在不同的层次抛出,在不同的位置抛出,可能会导致不同的finally语句块执行顺序。
7. finally语句块一定会执行吗?
public class SystemExitAndFinally { public static void main(String[] args) { try{ System.out.println("in main"); throw new Exception("Exception is thrown in main"); //System.exit(0); } catch(Exception e) { System.out.println(e.getMessage()); System.exit(0); } finally { System.out.println("in finally"); } }}
不一定,因为System.exit(0);finally不执行。
8.异常的传播路径
// UsingExceptions.java// Demonstrating the getMessage and printStackTrace// methods inherited into all exception classes.public class PrintExceptionStack { public static void main( String args[] ){ try { method1(); } catch ( Exception e ) { System.err.println( e.getMessage() + "\n" ); e.printStackTrace(); } } public static void method1() throws Exception{ method2(); } public static void method2() throws Exception{ method3(); } public static void method3() throws Exception{ throw new Exception( "Exception thrown in method3" ); }}
总结:
Try语句可以被嵌套。也就是说,一个try语句可以在另一个try块内部。每次进入try语句,异常的前后关系都会被推入堆栈。如果一个内部的try语句不含特殊异常的catch处理程序,堆栈将弹出,下一个try语句的catch处理程序将检查是否与之匹配。这个过程将继续直到一个catch语句匹配成功,或者是直到所有的嵌套try语句被检查耗尽。如果没有catch语句匹配,Java的运行时系统将处理这个异常。
9.受控异常与不受控异常
throws语句中声明的异常称为受控(checked)的异常,通常直接派生自Exception类。
RuntimeException(其基类为Exception) 和Error(基类为Throwable)称为非受控的异常。这种异常不用在throws语句中声明。
例子:
import java.io.*;public class CheckedExceptionDemo { public static void main(String[] args) { try { BufferedReader buf = new BufferedReader( new InputStreamReader(System.in)); //抛出受控的异常 System.out.print("请输入整数: "); int input = Integer.parseInt(buf.readLine()); //有可能引发运行时异常 System.out.println("input x 10 = " + (input*10)); } //以下异常处理语句块是必须的,否则无法通过编译 catch(IOException e) { System.out.println("I/O错误"); } //以下异常处理语句块可以省略,不影响编译,但在运行时出错 catch(NumberFormatException e) { System.out.println("输入必须为整数"); } } }
import java.util.InputMismatchException;import java.util.Scanner;public class Test{ public static void main(String[] args){ int score = 0; System.out.print("输入一个整数:"); Scanner sc = new Scanner(System.in); try{ score = sc.nextInt(); if(score < 0 || score >100){ throw new InputMismatchException(); } } catch(InputMismatchException e){ System.out.println("输入必须为整数(0-100之间)"); System.exit(0); } if(score >= 0 && score <=100){ if(score >= 90){ System.out.println("优"); } else if(score >= 80){ System.out.println("良"); } else if(score >= 70){ System.out.println("中"); } else if(score >= 60){ System.out.println("及格"); } else{ System.out.println("不及格"); } } }}