异常处理(程序健壮性→功能→性能)

异常 (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
 }

原文地址:https://www.cnblogs.com/sengzhao666/p/9941664.html