一、异常的概念
异常,也就是非正常情况。
其实。异常本质上是程序上的错误,包含程序逻辑错误和系统错误。
错误在我们编敲代码的过程中会常常发生,包含编译期间和执行期间的错误,在编译期间出现的错误有编译器帮助我们一起修正,然而执行期间的错误便不是编译器力所能及了。假若程序在执行期间出现了错误,假设置之不理。程序便会终止或直接导致系统崩溃,显然这不是我们希望看到的结果。因此,怎样对执行期间出现的错误进行处理和补救呢?Java提供了异常机制来进行处理,通过异常机制来处理程序执行期间出现的错误。通过异常机制,我们能够更好地提升程序的健壮性。
二、了解Java异常分类
在Java中异常被当做对象来处理。根类是java.lang.Throwable类,在Java中定义了非常多异常类(如OutOfMemoryError、NullPointerException、IndexOutOfBoundsException等),这些异常类分为两大类:Error和Exception。
Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类。各自都包括大量子类。
Error是无法处理的异常,比方OutOfMemoryError,一般发生这样的异常,JVM会选择终止程序。表示执行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关。而表示代码执行时 JVM(Java 虚拟机)出现的问题。比如,Java虚拟机执行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时。将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)通常会选择线程终止
Exception,也就是我们经常见到的一些异常情况,比方NullPointerException、IndexOutOfBoundsException,是程序本身能够处理的异常。
Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 经常使用操作”引发的错误。比如,若试图使用空值对象引用、除数为零或数组越界,则分别引发执行时异常(NullPointerException、ArithmeticException)和ArrayIndexOutOfBoundException。
注意:异常和错误的差别:异常能被程序本身能够处理,错误是无法处理。
Exception类的异常包含checkedexception和unchecked exception(uncheckedexception也称执行时异常RuntimeException,当然这里的执行时异常并非前面我所说的执行期间的异常。仅仅是Java中用执行时异常这个术语来表示,Exception类的异常都是在执行期间发生的)。
可查异常(编译器要求必须处置的异常):正确的程序在执行中,非常easy出现的、情理可容的异常状况。可查异常尽管是异常状况,但在一定程度上它的发生是能够估计的,并且一旦发生这样的异常状况,就必须採取某种方式进行处理。
除了RuntimeException及其子类以外。其它的Exception类及其子类都属于可查异常。这样的异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它。否则编译不会通过。
不可查异常(编译器不要求强制处置的异常):包含执行时异常(RuntimeException与其子类)和错误(Error)。
Exception 这样的异常分两大类执行时异常和非执行时异常(编译异常)。程序中应当尽可能去处理这些异常。
执行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常。程序中能够选择捕获处理,也能够不处理。这些异常通常是由程序逻辑错误引起的。程序应该从逻辑角度尽可能避免这类异常的发生。
执行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没实用try-catch语句捕获它。也没实用throws子句声明抛出它。也会编译通过。
非执行时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常。假设不处理,程序就不能编译通过。如IOException、SQLException等以及用户自己定义的Exception异常,普通情况下不自己定义检查异常。
第一种方式:直接在函数头中throws SomeException,函数体中不须要try/catch。
<span style="font-size:18px;"><span style="font-size:18px;"> 1. boolean testEx2() throws Exception{ 2. boolean ret = true; 3. int b=12; 4. int c; 5. for (int i=2;i>=-2;i--){ 6. c=b/i; 7. System.out.println("i="+i); 8. } 9. return true; 10.}</span></span>
另外一种方式:使用try/catch,在catch中进行一定的处理之后(假设有必要的话)抛出某种异常。
<span style="font-size:18px;"><span style="font-size:18px;">1. boolean testEx2() throws Exception{ 2. boolean ret = true; 3. try{ 4. int b=12; 5. int c; 6. for (int i=2;i>=-2;i--){ 7. c=b/i; 8. System.out.println("i="+i); 9. } 10. return true; 11. }catch (Exception e){ 12. System.out.println("testEx2, catch exception"); 13. Throw e; 14. } 15. }</span></span>
第三种方法:使用try/catch/finally,在catch中进行一定的处理之后(假设有必要的话)抛出某种异常。
<span style="font-size:18px;"><span style="font-size:18px;">1. boolean testEx2() throws Exception{ 2. boolean ret = true; 3. try{ 4. int b=12; 5. int c; 6. for (int i=2;i>=-2;i--){ 7. c=b/i; 8. System.out.println("i="+i); 9. throw new Exception("aaa"); 10. } 11. return true; 12. }catch (java.lang.ArithmeticException e){ 13. System.out.println("testEx2, catch exception"); 14. ret = false; 15. throw new Exception("aaa"); 16. }finally{ 17. System.out.println("testEx2, finally; return value="+ret); 18. } 19.}</span></span>
四、 异常捕获及处理:
在Java中假设须要处理异常,必须先对异常进行捕获,然后再对异常情况进行处理。怎样对可能发生异常的代码进行异常捕获和处理呢?使用try和catchkeyword就可以,如以下一段代码所看到的:
<span style="font-size:18px;">try {
File file = new File("d:/a.txt");
if(!file.exists())
file.createNewFile();
}catch (IOException e) {
// TODO: handle exception
}</span>
被try块包围的代码说明这段代码可能会发生异常,一旦发生异常。异常便会被catch捕获到,然后须要在catch块中进行异常处理。
这是一种处理异常的方式。
在Java中还提供了还有一种异常处理方式即抛出异常。顾名思义,也就是说一旦发生异常。我把这个异常抛出去,让调用者去进行处理。自己不进行详细的处理,此时须要用到throw和throwskeyword。
以下看一个演示样例:
public class Main { public static void main(String[] args) { try { createFile(); }catch (Exception e) { // TODO: handle exception } } public static void createFile()throws IOException{ File file = new File("d:/a.txt"); if(!file.exists()) file.createNewFile(); } }
这段代码和上面一段代码的差别是,在实际的createFile方法中并没有捕获异常,而是用throwskeyword声明抛出异常,即告知这种方法的调用者此方法可能会抛出IOException。
那么在main方法中调用createFile方法的时候,採用try...catch块进行了异常捕获处理。
当然还能够採用throwkeyword手动来抛出异常对象。以下看一个样例:
<span style="font-size:18px;">public class Main { public static void main(String[] args) { try { int[] data = new int[]{1,2,3}; System.out.println(getDataByIndex(-1,data)); }catch (Exception e) { System.out.println(e.getMessage()); } } public static int getDataByIndex(int index,int[] data) { if(index<0||index>=data.length) throw new ArrayIndexOutOfBoundsException("数组下标越界"); return data[index]; } }</span>
然后在catch块中进行捕获。
也就说在Java中进行异常处理的话。对于可能会发生异常的代码。能够选择三种方法来进行异常处理:
1)对代码块用try..catch进行异常捕获处理。
2)在 该代码的方法体外用throws进行抛出声明,告知此方法的调用者这段代码可能会出现这些异常,你须要慎重处理。此时有两种情况:
假设声明抛出的异常是非执行时异常,此方法的调用者必须显示地用try..catch块进行捕获或者继续向上层抛出异常。
假设声明抛出的异常是执行时异常,此方法的调用者能够选择地进行异常捕获处理。
3)在代码块用throw手动抛出一个异常对象,此时也有两种情况。跟2)中的类似:
假设抛出的异常对象是非执行时异常。此方法的调用者必须显示地用try..catch块进行捕获或者继续向上层抛出异常。
throws和thowkeyword
1)throws出如今方法的声明中。表示该方法可能会抛出的异常。然后交给上层调用它的方法程序处理,同意throws后面跟着多个异常类型。
2)通常会用于程序出现某种逻辑时程序猿主动抛出某种特定类型的异常。
throw仅仅会出如今方法体中,当方法在运行过程中遇到异常情况时,将异常信息封装为异常对象。然后throw出去。throwkeyword的一个很关键的数据就是 异常类型的转换(会在后面阐述道)。
throws表示出现异常的一种可能性。并不一定会发生这些异常;throw则是抛出了异常,运行throw则一定抛出了某种异常对象。两者都是消极处理异常的方式(这里的消极并非说这样的方式不好)。仅仅是抛出或者可能抛出异常,可是不会由方法去处理异常。真正的处理异常由此方法的上层调用处理。
五、异常的使用
1、使用已有的异常类,假如为IOException、SQLException。
try{
程序代码
}catch(IOException ioe){
程序代码
}catch(SQLException sqle){
程序代码
}finally{
程序代码
}
2、自己定义异常类
创建Exception或者RuntimeException的子类就可以得到一个自己定义的异常类。比如:
<span style="font-size:18px;">public class MyException extends Exception{ public MyException(){} public MyException(String smg){ super(smg); } }</span>
3、使用自己定义的异常
用throws声明方法可能抛出自己定义的异常。并用throw语句在适当的地方抛出自己定义的异常。比如:
在某种条件抛出异常
<span style="font-size:18px;">public void test1() throws MyException{ ... if(....){ throw new MyException(); } }</span>
将异常转型(也叫转译),使得异常更易读易于理解
<span style="font-size:18px;">public void test2() throws MyException{ ... try{ ... }catch(SQLException e){ ... throw new MyException(); } }</span>
另一个代码,非常有意思:
<span style="font-size:18px;">public void test2() throws MyException{ ... try { ... } catch (MyException e) { throw e; } }</span>
这段代码实际上捕获了异常,然后又和盘托出,没有一点意义,假设这样还有什么优点理的,不处理即可了,直接在方法前用throws声明抛出不就得了。异常的捕获就要做一些有意义的处理。
Java常见异常
在Java中提供了一些异经常使用来描写叙述经常发生的错误,对于这些异常,有的须要程序猿进行捕获处理或声明抛出。有的是由Java虚拟机自己主动进行捕获处理。Java中常见的异常类:
1. runtimeException子类:
1、 java.lang.ArrayIndexOutOfBoundsException
数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
2、java.lang.ArithmeticException
算术条件异常。譬如:整数除零等。
3、java.lang.NullPointerException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、訪问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
4、java.lang.ClassNotFoundException
找不到类异常。当应用试图依据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到相应名称的class文件时,抛出该异常。
5、java.lang.NegativeArraySizeException 数组长度为负异常
6、java.lang.ArrayStoreException 数组中包括不兼容的值抛出的异常
7、java.lang.SecurityException 安全性异常
8、java.lang.IllegalArgumentException 非法參数异常
2.IOException
IOException:操作输入流和输出流时可能出现的异常。
EOFException 文件已结束异常
FileNotFoundException 文件未找到异常
3. 其它
ClassCastException 类型转换异常类
ArrayStoreException 数组中包括不兼容的值抛出的异常
SQLException 操作数据库异常类
NoSuchFieldException 字段未找到异常
NoSuchMethodException 方法未找到抛出的异常
NumberFormatException 字符串转换为数字抛出的异常
StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
IllegalAccessException 不同意訪问某类异常
InstantiationException 当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时。抛出该异常