课后作业5
动手动脑1:请阅读并运行AboutException.java示例,然后通过后面的几页PPT了解Java中实现异常处理的基础知识。
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"); } } }
结果:控制台报错:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at AboutException.main(Main.java:7)
异常原因:在Java中进行除法操作时除数为零导致
动手动脑:阅读以下代码(CatchWho.java),写出程序运行结果
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"); } } }
运行结果:
ArrayIndexOutOfBoundsException/内层try-catch
发生ArithmeticException
动手动脑:多层的异常捕获-2:写出CatchWho2.java程序运行的结果
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"); } } }
结果:ArrayIndexOutOfBoundsException/外层try-catch
根据这段代码的逻辑,首先会抛出一个 ArrayIndexOutOfBoundsException 异常。然后,在内层的 try-catch 块中,尽管使用的是 catch(ArithmeticException e),但由于抛出的是 ArrayIndexOutOfBoundsException 异常,所以这个 catch 块中的代码不会执行。这是因为 catch 块只会捕获与其声明的异常类型相匹配的异常。
接下来,异常会传递到外层的 catch(ArrayIndexOutOfBoundsException e) 块中。由于异常类型匹配,所以这个 catch 块中的代码会执行。执行的结果是输出字符串 “ArrayIndexOutOfBoundsException/外层try-catch”。
所以,根据代码的逻辑分析,运行结果应该是 “ArrayIndexOutOfBoundsException/外层try-catch”。非常抱歉之前给出了错误的答案,希望这次能够给出正确的解释。
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"); } } }
结果:
in Level 1
in Level 2
in Level 3
Level 3:class java.lang.ArithmeticException
In Level 3 finally
Level 2:class java.lang.ArithmeticException
In Level 2 finally
Level 1:class java.lang.ArithmeticException
In Level 1 finally
动手动脑:辨析:finally语句块一定会执行吗? 请通过 SystemExitAndFinally.java示例程序回答上述问题
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"); } } }
结果:
in main
Exception is thrown in main
结论:finally不一定执行,因为 System.exit(0);结束了程序
如何跟踪异常的传播路径
当程序中出现异常时,JVM会依据方法调用顺序依次查找有关的错误处理程序。 可使用printStackTrace 和 getMessage方法了解异常发生的情况: printStackTrace:打印方法调用堆栈。 每个Throwable类的对象都有一个getMessage方法,它返回一个字串,这个字串是在Exception构造函数中传入的,通常让这一字串包含特定异常的相关信息。 请通过 PrintExpressionStack.java示例掌握上述内容。
// 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" ); } }
运行结果:
Exception thrown in method3
java.lang.Exception: Exception thrown in method3
at PrintExceptionStack.method3(PrintExceptionStack.java:28)
at PrintExceptionStack.method2(PrintExceptionStack.java:23)
at PrintExceptionStack.method1(PrintExceptionStack.java:18)
at PrintExceptionStack.main(PrintExceptionStack.java:8)
抛出多个受控异常的方法
一个方法可以声明抛出多个异常 int g(float h) throws OneException,TwoException { …… } ThrowMultiExceptionsDemo.java示例展示了相关特性。 注意一个Java异常处理中的一个比较独特的地方:
import java.io.*; public class ThrowMultiExceptionsDemo { public static void main(String[] args) { try { throwsTest(); } catch(IOException e) { System.out.println("捕捉异常"); } } private static void throwsTest() throws ArithmeticException,IOException { System.out.println("这只是一个测试"); // 程序处理过程假设发生异常 throw new IOException(); //throw new ArithmeticException(); } }
结果:
这只是一个测试
捕捉异常
子类抛出受控异常的限制
一个子类的throws子句抛出的异常,不能是其基类同名方法抛出的异常对象的父类。 OverrideThrows.java示例展示了Java的这个语法特性。
import java.io.*; public class OverrideThrows { public void test()throws IOException { FileInputStream fis = new FileInputStream("a.txt"); } } class Sub extends OverrideThrows { //如果test方法声明抛出了比父类方法更大的异常,比如Exception //则代码将无法编译…… public void test() throws FileNotFoundException { //... } }