Java异常处理 (try catch finally throw throws exception error)

xiaoxiao2021-02-28  81

原文地址:http://chenxiaoqiong.com/articles/tryCatch/

异常分类

     Throwable是所有异常的基类,程序中一般不会直接抛出Throwable对象。Exception和Error是Throwable的子类,Exception下面又有RuntimeException和一般的Exception两类。可以把JAVA异常分为三类:

检查性异常(非RuntimeException):所有继承自Exception并且不是RuntimeException的异常都是checked Exception。JAVA 语言规定必须对此类异常作处理,编译器会对此作检查,要么在方法体中声明抛出,要么使用catch语句捕获,不然不能通过编译。

运行时异常(RuntimeException):与检查性异常相反, 编译器不会检查程序是否对RuntimeException作了处理。RuntimeException发生的时候,表示程序中出现了编程错误,所以应该找出错误修改程序,而不是去简单的捕获或者抛出。

错误(Error): Error表示程序在运行期间出现了十分严重、不可恢复的错误,在这种情况下应用程序只能中止运行,例如JAVA 虚拟机出现错误。编译器不会检查Error是否被处理,在程序中不用捕获Error类型的异常;一般情况下,在程序中也不应该抛出Error类型的异常。

捕获异常try catch finally

在Java中,异常通过try-catch语句捕获。其一般语法形式为:

try { // 可能会发生异常的程序代码 } catch (Type1 id1) { // 捕获并处理try抛出的异常类型Type1 } catch (Type2 id2) { // 捕获并处理try抛出的异常类型Type2 } finally { // 无论是否发生异常,都将执行的语句块 }

try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。 catch 块:用于处理try捕获到的异常。 finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。在以下4种特殊情况下,finally块不会被执行: 1)在finally语句块中发生了异常。 2)在前面的代码中用了System.exit()退出程序。 3)程序所在的线程死亡。 4)关闭CPU。 执行过程:当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句;

抛出异常throw throws

throws关键字放在方法签名的尾部,一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。如果一个方法可能会出现异常,但没有能力处理这种异常,则在方法声明处用throws子句来声明抛出异常。语法格式:

methodName throws Exception1,Exception2,.. { }

当方法抛出上面的Exception1,Exception2,.. 异常时,方法将不对这些类型及其子类类型的异常作处理,而由调用该方法的调用者去处理。如果调用者不想处理该异常,可以继续向上抛出。如果所有方法都层层上抛获取的异常,最终JVM会进行处理(打印异常消息和堆栈信息)。

throw关键字总是出现在函数体中,用来抛出一个Throwable类型的异常。语法格式:

// 例如抛出一个IOException类的异常对象: throw new IOException;

throw语句后的语句执行不到。如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型。该方法的调用者也必须检查处理抛出的异常。

常用异常方法

下面的列表是 Throwable 类的主要方法:

方法名说明public String getMessage()返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。public Throwable getCause()返回一个Throwable 对象代表异常原因。public void printStackTrace()打印toString()结果和栈层次到System.err,即错误输出流。public String toString()使用getMessage()的结果返回类的串级名字。

常见异常

1. runtimeException子类:

异常说明java.lang.ArrayIndexOutOfBoundsException数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。java.lang.ArithmeticException算术条件异常。譬如:整数除零等。java.lang.NullPointerException空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等java.lang.ClassNotFoundException找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。java.lang.NegativeArraySizeException数组长度为负异常java.lang.ArrayStoreException数组中包含不兼容的值抛出的异常java.lang.SecurityException安全性异常java.lang.IllegalArgumentException非法参数异常

2.IOException

异常说明IOException操作输入流和输出流时可能出现的异常。EOFException文件已结束异常FileNotFoundException文件未找到异常

3. 其他

异常说明ClassCastException类型转换异常类ArrayStoreException数组中包含不兼容的值抛出的异常SQLException操作数据库异常类NoSuchFieldException字段未找到异常NoSuchMethodException方法未找到抛出的异常NumberFormatException字符串转换为数字抛出的异常StringIndexOutOfBoundsException字符串索引超出范围抛出的异常IllegalAccessException不允许访问某类异常InstantiationException当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常

注意事项

子类抛出的异常必须是父类抛出异常的一个子集,不能抛出新异常。不要让try块过于庞大 阅读代码的时候,在try块冗长的代码中,不容易知道到底是哪些代码会抛出哪些异常,不利于代码维护。使用try捕获异常是以程序执行效率为代价的,将不需要捕获异常的代码包含在try块中,影响了代码执行的效率。finally语句块中不要抛出异常,不要使用return   JAVA异常处理机制保证无论在任何情况下必须先执行finally块然后在离开try块,因此在try块中发生异常的时候,JAVA虚拟机先转到finally块执行finally块中的代码,finally块执行完毕后,再向外抛出异常。如果在finally块中抛出异常,try块捕捉的异常就不能抛出,外部捕捉到的异常就是finally块中的异常信息,而try块中发生的真正的异常堆栈信息则丢失了。 例子: public class TestException { public TestException() { } boolean testEx() throws Exception { boolean ret = true; try { ret = testEx1(); return ret; } catch (Exception e) { System.out.println("testEx, catch exception"); ret = false; throw e; } finally { System.out.println("testEx, finally; return value=" + ret); } } boolean testEx1() throws Exception { boolean ret = true; try { int b = 12; for (int i = 2; i >= -2; i--) { int c = b / i; System.out.println("i=" + i); } return true; } catch (Exception e) { System.out.println("testEx1, catch exception"); ret = false; throw e; } finally { System.out.println("testEx1, finally; return value=" + ret); //此处抛出新的异常,将覆盖catch中抛出的异常 //throw new Exception("testEx1, finally; throw new Exception"); //此处return,catch中排出的异常将无法捕获 return ret; } } public static void main(String[] args) { TestException testException1 = new TestException(); try { testException1.testEx(); } catch (Exception e) { System.out.println(e.getMessage()); } } }

建议:当你需要一个地方来执行在任何情况下都必须执行的代码时,使用finally块。比如当你的程序中使用了外界资源,如数据库连接,文件等,使用finally块来释放资源。 4. 不要一次捕获所有异常

try { method1(); //method1抛出ExceptionA method2(); //method1抛出ExceptionB method3(); //method1抛出ExceptionC } catch(Exception e) { …… }

这里有两个潜在的缺陷 - 分别处理就不能实现:针对try块中抛出的每种Exception,很可能需要不同的处理和恢复措施 - 代码中捕获了所有可能抛出的RuntimeException而没有作任何处理,掩盖了编程的错误,会导致程序难以调试。

正确代码:

try { method1(); //method1抛出ExceptionA method2(); //method1抛出ExceptionB method3(); //method1抛出ExceptionC } catch(ExceptionA e) { …… } catch(ExceptionB e) { …… } catch(ExceptionC e) { …… }
转载请注明原文地址: https://www.6miu.com/read-71856.html

最新回复(0)