黑马程序员技术交流社区

标题: 异常总结 [打印本页]

作者: 李道福    时间: 2013-9-16 19:19
标题: 异常总结
本帖最后由 李道福 于 2013-9-17 14:03 编辑

/*
java将所有的错误封装成为一个对象,其根本父类为Throwable

Throwable
--Error:指的是底层的、低级的、不可恢复的严重错误。此时程序一定会退出,
   因为已经失去了运行所必须的物理环境,一般不编译特定的代码进行处理
--Exception:要用针对性的处理方式进行处理
  --RunntimeException:运行时异常,可以不进行处理
       这类异常可以不捕获或声明,编译可以通过
  --非RunntimeException:要进行处理,这类异常要捕获或是声明,不然编译无法通过

1.异常的处理方式:
第一种方式:捕获
  (1).后面可以跟多个catch异常对象,但异常对象应该按由子类到父类的方式排列
   如果父类异常排在子类的前面,那么后面的子类异常会执行不到
   
  try{
   可能出现异常的代码
  }catch(异常类型,变量){
   异常处理方式
  }
  
  (2).finally是一定会执行的语句,一般用来关闭资源
  
  try{
   可能出现异常的代码
  }catch(异常类型,变量){
   异常处理方式
  }finally{
   一定会执行的语句
  }
  
  (3).其实这种方式并不能捕获异常,因为没有catch进行处理,当try中出现异常时,程序还是
   会直接抛出异常给上级(指的运行时异常,非运行时异常编译不通过)
  
  try{
   可能会出现异常的代码
  }finally{
   一定会执行的语句
  }

第二种方式:声明
  在函数内部直接将异常抛出,并在函数上声明这个异常,将异常交由上一级处理
  throw与throws区别
  throw:用在函数内部,在函数内部抛出异常,后面跟的是异常对象
  throws:用在函数上,后面跟的是异常类,并且可以跟多个异常类,中间有逗号分开

*/
//第一种方式:捕获异常
public class ExceptionTest{
public static void main(String[] args){
  div(4,7);
  System.out.println("main code");
}

public static void div(int a,int b){
  //捕获异常,当出现异常时,语句直接跳转到catch中进行异常的处理,try中出现异常的后面的语句就不会执行了
  try{
    int temp=a/b;
    int[] num=new int[a];
    System.out.println("temp="+temp);
    System.out.println(num[a]);
   }catch(ArithmeticException e){
    e.printStackTrace();
    //try后可以跟多个catch,应按照子类到父类的排列顺序,
    //如果try中出现了catch中所有的异常,那么程序会直接抛出异常给上一级


   }catch(ArrayIndexOutOfBoundsException e){
    e.printStackTrace();
    //finally中执行的一般是关闭资源的操作
   }finally{
    System.out.println("一定会执行的语句");
   }
}
}

//第二种方式:声明异常
public class ExceptionTest{
public static void main(String[] args) throws Exception{
  //调用者可以进行try或在函数上声明,如果进行了try那后面的语句还会执行,只是声明那后面的语句就不会执行了
  div(4,0);
  System.out.println("main code");
}
//在函数上声明异常,将异常交由上一级处理
public static void div(int a,int b) throws Exception{
  int temp=a/b;
  System.out.println("temp="+temp);
}
}

/*  
2.自定义异常类:必须是自定义类继承Exception类体系
     因为异常类和异常对象都要具有可抛性,这个可抛性是Throwable这个体系中独有特点,所有自定义异常类要继承于
     这个体系,也只有这个体系中的类才可以被throw和throws所操作
*/


//如果不想对自定义的异常类进行处理,可以让自定义类继承RuntimeException
class MyException extends Exception {
  MyException(String message){
  super(message);
}
}
public class ExceptionTest{
public static void main(String[] args) throws MyException{
  show(-1);
}
public static void show(int a) throws MyException{
  if(a<0)
  //抛出自定义异常类
   throw new MyException("角标为负数");
  int[] num=new int[a];
  System.out.println("num="+num[a]);
}
}

/*
3.异常类在子父类中的体现:
子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常,如果子类发生了异常,只能进行try
*/
class MyException extends Exception {
  MyException(String message){
  super(message);
}
}
class Father{
String str="lidaofu";
char[] name=str.toCharArray();
//父类抛出的异常
public void show(int index) throws ArrayIndexOutOfBoundsException{
  System.out.println("name["+index+"]"+name[index]);
}
}
class Son extends Father{
int age=0;
//当子类继承父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类
//如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常,只能通过try--catch解决
public void show(int index) throws ArrayIndexOutOfBoundsException{
  System.out.println("name["+index+"]="+name[index]);
  try{
   if(age==0){
    throw new MyException("除数为零啦");
    //当throw单独存在时,后面不能跟语句,因为执行不到
    //System.out.println(age);编译失败,这句话是执行不到的
    }
   int temp=index/age;
   System.out.println("temp="+temp);
  }catch(MyException e){
   e.printStackTrace();
  }
}
}
public class ExceptionTest{
public static void main(String[] args) throws MyException{
  Son s=new Son();
  s.show(3);
  System.out.println("main code");
}
}


/*
4.finally的执行时间问题
  finally语句是在return语句之后,跳转到上一级程序之前执行(即return语句中间执行)
  finally中的语句一定会执行,是建立在对应的try得到执行情况下,如果程序在try语句之前就发生了
  异常或就已经结束,那finally中的语句是不会执行的
  finally在一种情况下不会执行,System.exit(0):程序停止运行,退出虚拟机
*/
public class ExceptionTest{
public static void main(String[] args){
  System.out.println(test());
}
public static String test(){  
     try{  
   System.out .println("try block");  
   return test1 ();  
  } finally {  
   System.out .println("finally block");
   //return "finally"; 如果finally中有返回值,那么finally返回值就会替换掉上一级方法中的返回值
   //     这一句如果执行,那程序上一级方法中的after return 就会被finally所替换
  }  
}  
public static String test1(){  
  System.out.println("return statement");  
  return "after return";  
}
}
/*
程序结果为:
  try block
  return statement
  finally block
  after return

原因分析:
   1.try语句块,return test1(),则调用test1方法
   2.test1()执行后返回"after return",返回值"after return"保存在一个临时区域里
   3.执行finally语句块。若finally语句有返回值,则此返回值将替换掉临时区域的返回值
   4.将临时区域的返回值送到上一级方法中。
*/


public class ExceptionTest{
public static void main(String[] args){
  int a=5;
  int[] arr=new int[5];
  //return 0;要想让方法停止运行可以return或throw个异常
  int i=a/0;
  try{
   System.out.println(arr[6]);
  }catch(ArrayIndexOutOfBoundsException e){
   System.out.println(e.getMessage());
   System.out.println("角标越界");
  //这里的finally语句是不会执行的,因为在try语句之前程序就已经停止运行了
  }finally{
   System.out.println("finally");
  }
}
}











作者: 1098918523    时间: 2013-9-16 19:31
谢谢啦,总结的很全面,很有帮助
作者: 刘亮    时间: 2013-9-16 21:10
有收获呢~~~
作者: 酱爆    时间: 2013-9-16 21:11
我来支持下




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2