一、异常处理
1、现实生活的病
现实生活中万物在发展和变化会出现各种各样不正常的现象。
1:例如:人的成长过程中会生病。
|——病
|——不可治愈(癌症晚期)
|——可治愈
|——小病自行解决(上火,牙痛)
|——去医院(发烧)
2、程序中意外情况的处理方式
1 传统方式:用if语句进行判断,并作相应的处理。
public static void main(String[] args) { int x = 10; int y = 0; if(y==0){ System.out.println("除数不能为0"); }else{ int result = x/y; System.out.println(result); } System.out.println("程序结束!!!"); } |
2 抛出异常,捕获异常的机制
3、异常的含义
异常是java处理错误的一种机制。
设计良好的程序应该在异常发生的时候提供处理这些错误的方法,使得程序不会因为异常的发生而中断。
String friends[]={"tom","john","jenni"}; for(int i=0;i<4;i++){ System.out.println(friends[i]); } System.out.println("程序结束"); |
以上程序会因数组下标超出范围而中断,不会输出“程序结束!!!“
4、Java异常处理的机制
把异常的发现和处理相分离。
现实生活中的很多病况从面向对象的角度考虑也是一类事物,可以定义为类。
Java中可以通过类对这一类不正常的现象进行描述,并封装为对象。
5、异常的语法
Java的异常处理是通过5个关键字来实现的:try、catch、 finally、throw、throws。
使用try catch 来捕获异常
格式
public void method(){ try { 可能产生异常的 代码段 } catch (异常类型 e) { 对异常进行处理的代码段 } 代码段 } |
说明
try{ } 块表示受到监控的代码。其中一旦发生情况,就会按照是哪种情况,跳到catch块中执行。
e 是产生的异常对象的名字。每个异常发生的时候,都会有对应的异常对象。它记录了异常的详细信息。
示例代码
public static void main(String[] args) { String friends[]={"tom","john","jenni"}; try{ for(int i=0;i<4;i++){ System.out.println(friends[i]); } System.out.println("程序结束");
}catch(ArrayIndexOutOfBoundsException e){ /*System.out.println(e); System.out.println("数组下标越界了........."); e.printStackTrace();*/ System.out.println(e.getMessage()); } System.out.println("程序结束!!!"); } |
6、异常的分类
Java异常体系
|——Throwable (实现类描述java的错误和异常)
|——Error (错误)一般不通过代码去处理。
|——Exceprion (异常)
|——RuntimeException (运行时异常)
|——非运行时异常(受检查异常)
7、Error
错误(Error):
它指的是一个合理的应用程序不能截获的严重的问题。大多数都是反常的情况。错误是JVM的一个故障(虽然它可以是任何系统级的服务)。所以,错误是很难处理的,一般的开发人员是无法处理这些错误的。比如内存溢出,栈溢出等。
示例代码
public class Demo03_Error { public static void main(String[] args) { fun(); //java.lang.StackOverflowError Error 不需要使用try catch处理 } public static void fun(){ fun(); } } |
报错信息
Exception in thread "main" java.lang.StackOverflowError at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) at com.offcn.yichang.Demo03_Error.fun(Demo03_Error.java:12) |
8、Throwable类
- toString() 输出该异常的类名。
- getMessage() 输出异常的信息,需要通过构造方法传入异常信息(例如病态信息)。
- printStackTrace() 打印栈信息。
人生病:流鼻涕,感冒,呼吸道感染,肺炎。。。最后体现的是肺炎。
医生要处理需要获知这些信息。从外到里处理。最后找病源。
// Throwable able=new Throwable(); Throwable able = new Throwable("想吐。。。"); System.out.println(able.toString()); // 输出该异常的类名 System.out.println(able.getMessage()); // 输出异常的信息 able.printStackTrace(); // 打印栈 |
9、 运行时异常和非运行时异常
(1)运行时异常(RuntimeException)
运行时异常,不要求程序必须对它们做出处理。(在程序的编译期不会检查这种异常)
RuntimeException的子类:
ClassCastException
多态中,可以使用Instanceof 判断,进行规避
ArithmeticException
进行if判断,如果除数为0,进行return
NullPointerException
进行if判断,是否为null
ArrayIndexOutOfBoundsException
使用数组length属性,避免越界
示例代码
public class Demo05_运行时异常 { public static void main(String[] args) { Animal a = new Cat(); Dog d = (Dog)a; String str = null; "aaa".equals(str); str.charAt(0); str.concat("aaa"); } }
class Animal{ } class Cat extends Animal{ } class Dog extends Animal{ } |
说明:
这些异常是可以通过程序员的良好编程习惯进行避免的。
1:遇到运行时异常无需进行处理,直接找到出现问题的代码,进行规避。
2:就像人上火一样牙疼一样,找到原因,自行解决即可。
3:该种异常编译期不会检查程序员是否处理该异常。
4:如果是运行时异常,那么没有必要在方法上进行声明。
(2)非运行时异常(受检查异常)
如果出现了非运行时异常,必须进行处理,用throw或者try{}catch(){}处理,否则编译期报错。
1:IOException 使用要导入包import java.io.IOException;
2:ClassNotFoundException
3:FileNotFoundException
4:ParseException
例如:人食物中毒,必须进行处理,要去医院进行处理。
示例代码
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try { Date d = sdf.parse("aaa-10-10"); } catch (ParseException e) { e.printStackTrace(); } |
- 多重catch块
格式
try { 代码段 产生异常(异常类型2) } catch (异常类型1 e) { 对异常进行处理的代码段 } catch (异常类型2 e) { 对异常进行处理的代码段 } catch (异常类型3 e) { 对异常进行处理的代码段 } 代码段
|
示例代码
public class Demo07_多重catch块 { public static void main(String[] args) {
try { int x = 10; int y = 0; int result = x/y;
int[] aa = {1,2,3}; System.out.println(aa[1]);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); sdf.parse("1111-11-11");
Object obj = new Object(); Date d = (Date)obj; }catch(Exception e){ System.out.println("程序出错了~~~~~~~~~"); } /*catch (ParseException e) { System.out.println("转换错误"); }catch(ArithmeticException e){ System.out.println("运算错误"); }catch(ArrayIndexOutOfBoundsException e){ System.out.println("数组下标越界"); }catch(NullPointerException e){ System.out.println("空指针"); }*/ } } |
说明:
单个try块能有许多catch块,当try块有“可能引起不同类型异常”的语句时,多个catch块是必须的。
异常捕获的先后顺序应该“从小到大”。
11、程序中的异常处理
(1)自行处理
使用try{}catch()语句,保证程序可以正常运行。
(2)throws 关键字
当程序中发生异常时,无论是程序运行出现的运行时异常,编译阶段的非运行时异常,还是手工抛出的异常,都可以在程序中使用try{}catch进行处理。但也可以在当前的程序(也就是当前方法中),不做任何处理。使用throws关键字在方法声明时,进行异常的抛出,交给方法的调用者去处理。当方法的调用者也不知道如何处理,或不想处理时,可以继续向上抛出。
格式
类型 方法名(参数列表) throws 异常列表{ 代码 } |
示例代码
public static void method() throws ParseException,FileNotFoundException{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String str = "aaaa-11-11"; Date d = sdf.parse(str); FileInputStream is = new FileInputStream("D:/aaa.txt"); } |
(3)手工抛出异常 (throw关键字)
手工抛出异常,其效果和程序抛出异常是一样的,只是它是人为地抛出。
抛出异常的格式为:throw ThrowableObject
例如:throw new ArithmeticException();
示例代码
public static void main(String args[]) { System.out.print("Now"); try { System.out.print("is"); throw new NullPointerException(); // 直接抛出一个异常 ; // System.out.print("This will not execute!"); //此句不被执行 } catch (NullPointerException m) { System.out.print("the"); } System.out.print("time. \n"); } |
throw和throws的区别
- throw是对异常对象的抛出,throws是对异常的声明。
- throw是实实在在地抛出对象,一旦使用throw,一定会产生异常对象,throw只能跟一个异常对象。
- throws后面跟的异常的类名,可以跟多个,使用逗号隔开。
12、自定义异常
问题:现实中会出现新的病,就需要新的描述。
分析: Java的面向对象思想将程序中出现的特有问题进行封装。
当jdk内置异常类型不足以满足系统需求时,我们需要自定义异常类型。
使用自定义异常和使用jdk内置异常是一回事。
自定义异常的方式: 继承Exception 或 RuntimeException
示例代码
//自定义的运行时异常 public class MyException extends RuntimeException{ /* * 在自定义异常时,完全可以自定义一些属性和方法。但多数时间不需要这样做 * */ public MyException(){
} public MyException(String message){ super(message); } } |
示例代码2
// 自定义一个非运行时异常 public class MyException2 extends Exception { public MyException2(){
} public MyException2(String message){ super(message); } } |
案例:模拟吃饭没带钱的问题
- 定义吃饭功能,需要钱。(例如:eat(double money))
- 如果钱不够是不能吃饭,有异常。
- 自定义NoMoneyException();继承Exception 提供有参无参构造,调用父类有参构造初始化。eat 方法进行判断,小于10块,throw NoMoneyException("钱不够");
- eat 方法进行声明,throws NoMoneyException;
- 如果钱不够老板要处理。调用者进行处理。try{}catch(){} 。
示例代码
class NoMoneyException extends Exception { NoMoneyException() { } NoMoneyException(String message) { super(message); } } class Demo11 { public static void main(String[] args) { System.out.println(); try { eat(0); } catch (NoMoneyException e) { System.out.println("跟我干活吧。"); } } public static void eat(double money) throws NoMoneyException { if (money < 10) { throw new NoMoneyException("钱不够"); } System.out.println("吃桂林米粉"); } } |
13、finally
catch的目的,抓住出现的异常情况,使工作维持正轨。
finally的目的:
有某些事情,相当重要,即便是发生了异常,也不应该被跳过。
比如:还债
finally到底用在哪?
宋丹丹的经典错误:
开冰箱门 装入大象 关冰箱门 try { 开冰箱门 装入大象 关冰箱门 } catch() { 修理大象 } |
错在哪? 如果装大象的时候出了问题,冰箱门将不能关闭。
完美的方案:
打开冰箱门 try { 装入大象 } catch(…) { 修理大象 } finally { 关闭冰箱门 } |
finally通常用在:代码中有必须要执行的代码(比如释放资源)的情况。
注意: 同样也有 try{}finally{} 结构。
public static void main(String[] args) { /* System.out.println("111"); try{ System.out.println("222"); int result = 10/0; System.out.println("333");
}catch(Exception e){ System.out.println("444"); //return; String str = null; str.charAt(0); } System.out.println("555"); */ System.out.println("111"); try{ System.out.println("222"); int result = 10/0; System.out.println("333");
}catch(Exception e){ System.out.println("444"); //return; //即使有return finally的代码也要执行,在return之前执行 String str = null; str.charAt(0); }finally{ System.out.println("555"); } } |
考考你:
1…
try{
2…
3…
4…
}
finally{
5…
}
6…
请分别说出正常与异常执行的流程?
正常时:
1处发生异常:
3处发生异常:
14、常见异常举例
RuntimeException Java.lang包中多数异常的基类 ArithmeticException 算术异常,如除以0 ArrayIndexOutOfBoundsException 数组下标出界 NullPointerException 试图访问null对象引用 SecurityException 试图违反安全性 ClassNotFoundException 不能加载请求的类 NumberFormatException 字符串到数字格式的非法转换 IOException I/O异常的根类 FileNotFoundException 不能找到文件 IllegalAccessException 对类的访问被拒绝 NoSuchMethodException 请求的方法不存在 InterruptedException 线程中断 NullPointerException空指针异常 |