异常 (Exception):发生于程序执行期间,表明出现了一个非法的运行状况。许多JDK中的方法在检测到非法情况时,都会抛出一个异常对象。
例如:数组越界和被0除。
try {
//执行的代码,其中可能有异常。一旦发现异常,则立即跳到catch执行。否则不会执行catch里面的内容
}
catch {
//除非try里面执行代码发生了异常,否则这里的代码不会执行
}
finally {
//不管什么情况都会执行,包括try catch 里面用了return ,可以理解为只要执行了try或者catch,就一定会执行 finally
}
①把可能会发生错误的代码放进try语句块中。
②当程序检测到出现了一个错误时会抛出一个异常对象。异常处理代码会捕获并处理这个错误。
catch语句块中的代码用于处理错误。
③当异常发生时,程序控制流程由try语句块跳转到catch语句块。
④不管是否有异常发生,finally语句块中的语句始终保证被执行。
⑤如果没有提供合适的异常处理代码,JVM将会结束掉整个应用程序。
异常的“多态”特性:
1.①可以有多个catch语句块,每个代码块捕获一种异常。在某个try块后有两个不同的catch 块捕获两个相同类型的异常是语法错误。
②使用catch语句,只能捕获Exception类及其子类的对象。因此,一个捕获Exception对象的catch语句块可以捕获所有“可捕获”的异常。
③将catch(Exception e)放在别的catch块前面会使这些catch块都不执行,因此Java不会编译这个程序。
2.catch有几种写法:
catch
这将捕获任何发生的异常。
catch(Exception e)
这将捕获任何发生的异常。另外,还提供e参数,你可以在处理异常时使用e参数来获得有关异常的信息。
catch(Exception的派生类 e)
这将捕获派生类定义的异常,例如,我想捕获一个无效操作的异常,可以如下写:
catch(InvalidOperationException e)
{
....
}
这样,如果try语句块中抛出的异常是InvalidOperationException,将转入该处执行,其他异常不处理。
catch可以有多个,也可以没有,每个catch可以处理一个特定的异常。.net按照你catch的顺序查找异常处理块,如果找到,则进行处理,如果找不到,则向上一层次抛出。如果没有上一层次,则向用户抛出,此时,如果你在调试,程序将中断运行,如果是部署的程序,将会中止。
如果没有catch块,异常总是向上层(如果有)抛出,或者中断程序运行。
finally:
①资源泄露:当一个资源不再被某应用程序使用,但此程序并未向系统声明不再使用此资源时发生这种情况。
②finally语句块主要用于解决资源泄露问题,它位于catch语句块之后,JVM保证它们一定执行。
③注意:finally语句块中也可能发生异常,如果这种情况发生,先前的异常被放弃。
④当有多个嵌套的try…catch…finally时,要特别注意finally的执行时机。
⑤特别注意:
当有多层嵌套的finally时,异常在不同的层次抛出 ,在不同的位置抛出,可能会导致不同的finally语句块执行顺序。
JDK中与异常相关的类:
Throwable类有两个直接子类:
Exception:出现的问题是可以被捕获的;
Error:系统错误,通常由JVM处理。
可捕获的异常又可以分为两类:
(1)Check异常:直接派生自Exception的异常类,必须被捕获或再次声明抛出
(2)Runtime异常:派生自RuntimeException的异常类。使用throw语句可以随时抛出这种异常对象:
throw new ArithmeticException(…);
THROWS语句:
①throws语句表明某方法中可能出现某种(或多种)异常,但它自己不能处理这些异常,而需要由调用者来处理。
②当一个方法包含throws子句时,需要在调用此方法的代码中使用try/catch/finally进行捕获,或者是重新对其进行声明,否则编译时报错。
③throws语句中声明的异常称为受控(checked)的异常,通常直接派生自Exception类。
④RuntimeException(其基类为Exception) 和Error(基类为Throwable)称为非受控的异常。这种异常不用在throws语句中声明。//程序说明
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Sanj {
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("输入必须为整数");
}
}
}
输出:
⑤一个子类的throws子句抛出的异常,不能是其基类同名方法抛出的异常对象的父类。//程序说明
1 import java.io.*;
2
3
4 public class OverrideThrows
5 {
6 public void test()throws IOException
7 {
8 FileInputStream fis = new FileInputStream("a.txt");
9 }
10 }
11 class Sub extends OverrideThrows
12 {
13 //如果test方法声明抛出了比父类方法更大的异常,比如Exception
14 //则代码将无法编译……
15 public void test() throws FileNotFoundException
16 {
17 //...
18 }
19 }
Java 7 及以后的版本,允许在一个catch块中捕获多个异常。
示例代码如下:
try {
//...
throw new SocketException();
}
catch (SocketException | SecurityException | NullPointerException e) {
//exception handler
}