Java的异常处理——try-catch-finally-throw-throws
2015-12-31 12:49
686 查看
大一大二写了两年C++,好几万行的代码,从来没有写过异常处理方面的代码。C++的老师上课放过异常处理的PPT,但是没有布置过相关作业,平时写的代码也不会想去用异常处理。现在到了大三上学期,才第一次在数据库课程设计的程序中写了try-catch。本学期学Java,我要彻底弄清楚异常处理是怎么弄的。
其实在 catch { } 里面,理论上也可能抛出异常。写 catch 的时候要小心,保证不要出问题。如果在 catch 里面抛出了异常,那就hehe了。
在Java 7中,增加了多异常捕获,即一个catch可以同时捕获多个不同类型的异常。这个异常对象是final,其引用不能指向一个另外一个异常对象。
try-catch是可以嵌套的。需要注意的是:内层try抛出的异常,如果内层没有catch的话,由外层catch负责捕获。
从 Java 7 开始,try后面可以加一对圆括号,在这个圆括号里面,可以声明,初始化一个或多个资源。当 try 语句结束的时候,可以自动关闭资源。这样就不用finally,不用手动写 scanner.close() 了,JVM会自动帮我们做。
throws 声明抛出一个异常序列:在定义方法的时候使用。假设定义了方法foo( ),foo( )方法内部可能抛出异常MyException,但是foo( ) 内部没有catch MyException。于是定义 foo( ) throws MyException { }。这样 MyException 对象就由调用foo( ) 的上一级调用者进行处理。如果存在多级调用,“下面一级”抛出了一个异常对象,“上一级”捕获了,那么“更上一级”就无法捕获了,毕竟异常对象只有一个。
Exception类的构造方法有:super( ),和 super( String message ) 两种。
try-catch
下面的例子:多catch处理语句。一个catch捕获一个异常。出现异常的时候:停止try,按照代码里 catch 的顺序从上往下依次匹配异常类型,首次匹配成功后执行该 catch,后面的 catch 跳过,不用继续匹配。如果 catch 的顺序是:先捕获异常 e1, 其后面再捕获异常 e2,那么 e1 不能是 e2 父类。即父类异常要在子类异常的后面捕获。其实在 catch { } 里面,理论上也可能抛出异常。写 catch 的时候要小心,保证不要出问题。如果在 catch 里面抛出了异常,那就hehe了。
[code]package exception; import java.util.Scanner; public class MultiCatchDemo { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int array[] = new int[3]; try { System.out.println("input a number"); String str = scanner.next(); int n1 = Integer.parseInt(str); // str 转换成 int, 可能抛出 NumberFormatException System.out.println("input another number"); int n2 = scanner.nextInt(); array[1] = n1 / n2; // n2 等于 0 时,抛出ArithmeticException array[3] = n1 * n2; // 数组越界,抛出ArrayIndexOutOfBoundsException System.out.println("the sum of two numbers is" + (n1 + n2)); } catch (NumberFormatException ex) { System.out.println("数字格式化异常"); } catch (ArithmeticException ex) { System.out.println("算术异常"); } catch (ArrayIndexOutOfBoundsException ex) { System.out.println("数组下标越界异常"); } catch (Exception e) { System.out.println("其他未知异常"); } scanner.close(); // 物理资源回收 System.out.println("程序结束"); } }
在Java 7中,增加了多异常捕获,即一个catch可以同时捕获多个不同类型的异常。这个异常对象是final,其引用不能指向一个另外一个异常对象。
[code]catch (ArrayIndexOutOfBoundsException | NumberFormatException | ArithmeticException ex) { System.out.println("程序发生了数组越界,数字格式异常,算数异常之一"); // ex = new ArithmeticException("text"); 默认是常数,不能赋值 }
try-catch是可以嵌套的。需要注意的是:内层try抛出的异常,如果内层没有catch的话,由外层catch负责捕获。
[code]package exception; import java.io.FileInputStream; import java.io.IOException; import java.util.Scanner; public class NestingTryCatch { public static void main(String[] args) { // 外层try try(Scanner scanner = new Scanner(System.in)) // 自动关闭资源 { System.out.println("input one number"); String str = scanner.next(); int n1 = Integer.parseInt(str); // 内层try try { @SuppressWarnings({ "unused", "resource" }) FileInputStream fis = new FileInputStream("caitao.txt"); } catch (IOException ioe) { System.out.println(ioe.getMessage()); } System.out.println("input another number"); int n2 = scanner.nextInt(); System.out.println("n1/n2 = " + n1 / n2); } catch (Exception e) { e.printStackTrace(); } System.out.println("caitao"); } }
try-catch-finally
fianlly的作用一般是回收物理资源,比如:数据库连接,网络连接,磁盘文件读写等等。如果在try里面使用了物力资源,不管是否发生异常,都应该回收这些资源。不管是否发生异常,fianlly代码块里面的代码总会执行。Java的垃圾回收机制可以回收堆内存中对象占用的内存(也就是 new 操作符的东西),但是不能回收物理资源。[code]package exception; import java.io.FileInputStream; import java.io.IOException; public class FinallyDemo { public static void main(String[] args) { FileInputStream fis = null; try { fis = new FileInputStream("caitao.txt"); } catch (IOException ioe) { System.out.println(ioe.getMessage()); return; //System.exit(0); } finally { if (fis != null) { try { fis.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } System.out.println("执行finally块里的资源回收"); } } }
从 Java 7 开始,try后面可以加一对圆括号,在这个圆括号里面,可以声明,初始化一个或多个资源。当 try 语句结束的时候,可以自动关闭资源。这样就不用finally,不用手动写 scanner.close() 了,JVM会自动帮我们做。
[code]try(Scanner scanner = new Scanner(System.in)) { } catch () { } // 隐式的finally块,自动关闭资源
throw & throws
throw 抛出一个异常对象:程序出现异常的时候,系统会自动抛出异常对象,除此之外也可以用代码手动抛出异常对象(比如抛出自己写的一个异常类的对象,或者根据业务需要抛出异常对象)[code]package exception; import java.util.Scanner; public class ThrowDemo { public static void main(String[] args) { try(Scanner scanner = new Scanner(System.in)) { System.out.println("input your age: "); int age = scanner.nextInt(); if (age < 0 || age > 100) // 年龄超出范围则抛出异常 { throw new Exception("age is unlegal"); } } catch (Exception e) { e.printStackTrace(); } System.out.println("程序结束"); } }
throws 声明抛出一个异常序列:在定义方法的时候使用。假设定义了方法foo( ),foo( )方法内部可能抛出异常MyException,但是foo( ) 内部没有catch MyException。于是定义 foo( ) throws MyException { }。这样 MyException 对象就由调用foo( ) 的上一级调用者进行处理。如果存在多级调用,“下面一级”抛出了一个异常对象,“上一级”捕获了,那么“更上一级”就无法捕获了,毕竟异常对象只有一个。
[code]package exception; import java.util.Scanner; public class ThrowsDemo { public static void myThrowsFunction() throws NumberFormatException, ArithmeticException, Exception { // 这个方法可能抛出异常,但是没有自己处理。“甩锅”给上一级调用者 Scanner scanner = new Scanner(System.in); System.out.println("input a number"); String string = scanner.next(); int n1 = Integer.parseInt(string); System.out.println("input another number"); int n2 = scanner.nextInt(); System.out.println("n1/n2 = " + n1 / n2); scanner.close(); } public static void main(String[] args) { try { myThrowsFunction(); // 这个方法可能抛出异常,但是这个方法自己却没有处理。于是交给上一级(即 main 方法)处理 } catch (NumberFormatException e) { e.printStackTrace(); } catch (ArithmeticException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
自定义一个异常类
从 java.lang.Exception 可以继承一个检查型自定义类,也可以从 java.lang.RuntimeException 继承一个非检查型异常。Exception类的构造方法有:super( ),和 super( String message ) 两种。
[code]package exception; @SuppressWarnings("serial") class MyException extends Exception { private int i; public int val() { return i; } public MyException(){} public MyException(String msg) { super(msg); } public MyException(String msg, int i) { super(msg); this.i = i; } } public class MyExceptionDemo { public static void a() throws MyException { System.out.println("Throwing MyException from a()"); throw new MyException(); } public static void b() throws MyException { System.out.println("Throwing MyException from b()"); throw new MyException("Originated in b()"); } public static void c() throws MyException { System.out.println("Throwing MyException from c()"); throw new MyException("Originated in c()", 43); } public static void main(String[] args) { try { a(); } catch (MyException e) { e.getMessage(); } try { b(); } catch (MyException e) { e.toString(); } try { c(); } catch (MyException e) { e.printStackTrace(); System.out.println("error code: " + e.val()); } } }
相关文章推荐
- Java动态代理
- java.lang.UnsupportedOperationException异常解决办法
- java好书下载
- java POI读取excel 并保存在数据库中
- RxJava练习(3)--跳过与截取
- javaweb项目将文件上传至数据库中的大小限制
- struts2
- 使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句
- java基础tips
- struts2遍历map
- 在线预览-Java 使用 Print2Flash 实现Office文档在线阅读
- CXF3.0.2+Spring3.2.14 Web Service入门实例二
- java语言中数值自动转换的优先顺序
- Spring+Hibernate报错:Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL)
- java6 java与js交互
- java5、6、7特性
- eclipse编码
- Java内部类详解
- JAVA虚拟机、Dalvik虚拟机和ART虚拟机简要对比
- SpringMVC集成velocity模版