Java异常处理机制
      众所周知Java里所有的实现都是由类组成,程序在运行过程中肯定会有非正常情况。
Java把非正常情况分为两种,一种为Error(错误),一种为Exception(异常)。
所有的非正常情况的类都继承于Throwable。错误通常指与虚拟机有关的比如系统崩溃,虚拟机错误等这些错误无法恢复或者不可能捕获,所以应用程序无法处理。
所以Error在基本不算在异常处理机制中,我们主要讨论Exception。
Exception 又分为 RuntimeException异常 和 Checked异常。
下面要进入异常处理的具体情况了,异常机制主要依赖于try catch finally throw throws这五个关键字。
首先讲解 try catch
就像 if  else一样  可以形象的将  try catch写成这样

if(一切正常)
 {

 }
 else
 {


 }
 下面就是java异常处理机制的语法了
 try
 {

 }
 catch(Exception e)
 {
  ,  ,,,,,,,
 }


上述代码中如果在try块中执行代码时遇到了异常系统会自动生成一个异常对象,该异常对象被提交给java运行时环境,这个过程被称为抛出异常。
当java运行时环境收到异常对象时,会寻找处理该对象的catch块,如果找到合适的catch块就把该异常对象交给他处理这个过程称为捕获异常,如果找不到合适的catch块java程序就会退出
那么当java运行时环境收到异常对象时如何给该异常对象寻找合适的catch块?

try
 {
 }
 catch(ExceptionClass1 e1)
 {
 }
 catch(ExceptionClass2 e2)
 {
 }
 catch(ExceptionClass3 e3)
 {
 }


运行时环境将拿着下面的异常块中的异常类依次与异常对象进行比较如果相符合就进入catch块中不再向下找,如果不符合就继续向下寻找。
异常的类----Exception 为最原始的类
下面分别有RuntimeException IOException SQLException
RuntimeException 又有IndexOutOfBoundsException NullPointerException ClassCastException等
在写catch块时要特别注意catch(ExceptionClass1 e1)中异常类的从属关系
从属关系必须是 把子类写到上面的catch()中 父类在下。
因为如果父类在在上面的catch()中,由于java的转换机制异常对象直接就和他的父类配对成功,那么这样的异常处理肯定会有问题。例子如下:

public class DivTest
 {
     public static void main(String [] args)
    {
     try
    {    
     int a = Integer.parseInt(args[0]);
     int b = Integer.parseInt(args[1]);    
     int c = a / b;
     System.out.println("您输入的两个数相除的结果是: "+ c);
    }
    catch(IndexOutOfBoundsException e1)
     {
      System.out.println("数组越界:运行程序时输入的参数不够");
     }
    catch(NumberFormatException e2)
    {
     System.out.println("数字格式异常");

     }
     catch(Exception e3)
    {
      
      System.out.println("未知异常");
    }    
   }
 }


您可以把上面程序运行一下
然后再把

catch(Exception e3)
    {
      
      System.out.println("未知异常");
    }

这一块从最下面放到最上面再运行一下,您就知道结果了。

异常捕获可以总结为一句话  先处理小异常再捕获大异常。
也就是父类必须在子类的下面。
如果每次都写很多的catch块您一定会觉得烦,幸亏Java7提供了多异常捕获
使用catch块一次来捕获多个异常时需要注意两个地方
1捕获多异常时多个异常类型之间用|(竖线)分开
2捕获多种异常类型时,异常变量有隐式的final修饰,因此程序不能对异常变量重新复制。

public class DivTest
 {
     public static void main(String [] args)
    {
     try
    {    
     int a = Integer.parseInt(args[0]);
     int b = Integer.parseInt(args[1]);    
     int c = a / b;
     System.out.println("您输入的两个数相除的结果是: "+ c);
    }
    catch(IndexOutOfBoundsException|NumberFormatException e1)
     {
      System.out.println("程序发生了数组越界异常,数字格式错误异常之一");
         e1 = new ArithmeticException("test");//错误 ①
     }
     catch(Exception e3)
    {
      
      System.out.println("未知异常");
     e3 = new RuntimeException("test"); //正确  ②
    }    
   }
 }


之所以①错误而②正确正是因为捕获多种异常类型时,异常变量有隐式的final修饰,因此程序不能对异常变量重新复制。因为①中的异常变量是final型的所以更改会有错误,而②就没有问题。
使用finally回收资源
有些人可能会有疑问,java不是有自动的垃圾回收器吗?为什么还要回收资源?
Java的垃圾回收机制不会回收物理资源,垃圾回收机制只能回收堆内存中对象所占用的内存。
有时候你在try块中打开了一些物理资源(例如数据库连接,网络连接等)这些资源都必须由你自己显式回收。
为了保证回收物理资源java提供了finally块
finally块位于catch块的最后,不管try块中的代码是否出现异常,也不管哪一个catch块被执行,甚至在try,catch块中执行了return语句,finally块也总会被执行。
&&&在异常处理语法结构中只有try是必须的,如果没有try块则后面不能有catch和finally块,catch块和finally块时可选的,但是必须出现其中之一,也可以同时出现,可以有多个catch块出现但是finally块必须位于所有的catch块之后。
在java的try块或者catch块中如果使用return语句则finally块照样执行,但是如果使用了System.exit(1)语句来退出虚拟机,则不会执行finally块。
总结:除非在try catch块中调用了退出虚拟机的方法否则不管咋try catch中执行了怎样的代码,finally块总会被执行。
通常情况下不要在finally中执行return或者throw等导致方法终止的语句。一旦finally块中使用了return或throw语句,将导致try catch 中的return throw 语句失效。

public class FinallyFlowTest
 {
    public static void main(String [] args)
 {
    boolean a = test();
    System.out.println(a);
 }
 public static boolean test()
 {
    try
 {
   return true;
 }
  finally
 {
   return false;
 }
 }

 }

您可以执行上述代码做一个测试  执行上述程序使  try中的return true失去了作用。
使用throws语句声明抛出异常的思路是:当前放法不知道这种类型的异常,该异常应该由上一级调用者处理,如果main方法也不知道如何处理,也可以使用throws声明抛出异常,该异常将交给虚拟机,虚拟机对异常的处理方法是,打印异常的跟踪栈信息,并终止程序运行。
throws语法
throws ExceptionClass1,ExceptionClass2.。。。。。
throws声明抛出只能在方法签名中使用,throws可以抛出多个异常类但是每个异常类之间用逗号隔开。
使用throws声明抛出异常时有一个限制--“两小” 即  子类方法声明抛出的异常类型应该是父类抛出的异常类型的子类或者相同,子类方法声明抛出的异常数量不准比父类抛出的多。
也就是子类抛出的异常类型的等级要小于等于父类的 数量也要小于等于父类的。
使用throw抛出异常
当程序出现错误时系统会自动抛出异常,除此之外java也允许程序自行抛出异常,自行抛出异常使用throw来实现的。
需要注意throw和throws不同的是 throw抛出的不是异常类而是异常实例,而且每次只能抛出一个异常实例。
例如
throw new Exception("异常");
*********************************
这里要再一次提到一个重点的内容:
Exception异常  下有一个RuntimeException异常  其他的 均为Checked异常
RuntimeException异常 和  Checked异常是有很大的不同的,
当throw抛出的是Checked异常时  该throw语句要么处于try块里显式捕获该异常,要么是放在一个带有throws声明抛出的方法中,即把该异常交给该方法的调用者处理,但是如果throw抛出的是RuntimeException异常该语句就无需在try块中也无需在throws声明抛出的方法中,程序可以显式的调用try catch块来处理,也可以不理会将他交给方法调用者处理。
由此可以看出RuntimeException异常 比 Checked异常更加的灵活。
最后一点----自定义异常类
难道我们只能用Java规定好的各种异常类?
当然不!
我们可以自定义!
自定义异常类的注意点如下程序:

public class AutionException extends Exception
 {
     public AutionException(){}①
     public AutionException(String msg)②
   {
         super(msg);
   }
 }


注意点:自定义类都应该继承Exception基类

自定义类需要提供两个构造器一个是无参构造器,另一个是带一个字符参数的构造器

以上就是个人对Java异常处理的一点浅薄的学习