异常的笔记
------- android培训、java培训、期待与您交流! ----------
1 异常
1.1 java异常体系图
现实生活中的很多病况从面向对象的角度考虑也是一类事物,可以定义为类。
java中可以通过类对这一类不正常的现象进行描述,并封装为对象。
1. java的异常体系包含在java.lang这个包默认不需要导入。
2. java异常体系
|——Throwable (实现类描述java的错误和异常)
|——Error (错误)一般不通过代码去处理。
|——Exceprion (异常)
|——RuntimeException (运行时异常)
|——非运行时异常
常见的Error
错误原因:内存溢出。需要的内存已经超出了java虚拟机管理的内存范围。
错误原因:找不到类文件。
错误(Error):
它指的是一个合理的应用程序不能截获的严重的问题。大多数都是反常的情况。错误是JVM的一个故障(虽然它可以是任何系统级的服务)。所以,错误是很难处理的,一般的开发人员(当然不是你)是无法处理这些错误的。比如内存溢出.
3. 异常体系图的对应
1.2 Throwable类
Throwable是所有错误或者异常的父类。(描述java不正常情况的类的父类)
1. toString() 输出该异常的类名。
2. getMessage() 输出异常的信息,需要通过构造方法传入异常信息(例如病态信息)。
3. printStackTrace() 打印栈信息。
/* Throwable类 printStackTrace() 打印栈信息
肺炎 上呼吸道感染 发烧 流鼻涕感冒 小感冒 */ class Demo6 {
public static void main(String[] args) {
// Throwable able=new Throwable(); Throwable able = new Throwable("想吐。。。"); System.out.println(able.toString()); // 输出该异常的类名 System.out.println(able.getMessage()); // 输出异常的信息 able.printStackTrace(); // 打印栈信息 } } |
1.3 异常的处理方式
1.3.1处理方式1:捕获处理
捕获处理的格式:try-catch块 try{ 可能发生异常的代码... }catch(异常的类型 变量名){
异常处理的代码; } |
捕获处理注意的细节:
1. 如果try块中的代码出现了异常,然后异常经过了处理了之后,那么try-catch块外面的代码可以正常的执行。 2. 如果try块中的代码出现了异常,那么try块中出现异常的代码后面的代码无法正常执行的。 3. 一个try块后面可以跟有多个catch块,也就是一个try块可以捕获多种类型的异常对象。 4. 一个try块可以捕获多种类型的异常对象,但是捕获的异常类型的顺序必须从小到大进行捕获,否则报错。 |
class Demo7 { public static void main(String[] args) { //System.out.println("Hello World!"); int[] arr = {12,10,11}; //arr = null; div(4,0,arr); }
public static void div(int a ,int b ,int[] arr){ int c = 0; try{
System.out.println("数组的长度:"+ arr.length);
c = a/b; //可能会发生异常。 new ArithmeticException()(算术异常)
}catch(ArithmeticException e){ //科室 内科 //处理异常的代码 异常处理的代码是出现了对应的异常的时候才会执行的。 System.out.println("处理异常了..."); e.printStackTrace();
}catch(NullPointerException e){ //专门处理空指针异常的科室 System.out.println("处理了空指针异常...");
}catch(Exception e){ // 多态 Exception e = new NullPointerException(); System.out.println("我是急诊室,包治百病...");
} System.out.println("c = "+ c); } } |
1.3.2异常的处理方式2:抛出处理(throw throws)
抛出处理要注意的细节:
1. 如果一个方法内部抛出了一个编译时异常对象,那么必须要方法声明抛出。 2. 调用了一个声明抛出编译时异常类型 的方法,调用者必须要处理异常。 3. 在一种情况下,throw关键字后面不能跟有其他的语句,因为方法一旦执行了throw语句,那么这个方法会马上结束。 4. 在一种情况下,只能抛出一种类型的异常对象。 |
throw与throws关键字的区别:
1. throw关键字是用于方法内部抛出一个异常对象,throws关键字是用于在方法声明上声明抛出异常类型的。 2. throw关键字一次性只能抛出一个异常对象,throws关键字一次可以声明抛出多个异常类型。 |
何时使用抛出处理,何时使用捕获处理? 选择的原则?
凡是与用户直接接触 的代码遇到了异常都不能抛出,因为这时候抛出就抛给了用户,这时候用户的体验是非常差的。需要通知调用者这里已经出了问题的时候,这时候选择抛出处理。
class Demo8 { public static void main(String[] args) { //捕获处理 try{ int[] arr = null; div(4,0,arr);
}catch(Exception e){ System.out.println("出现了异常..."); System.out.println("toString:"+ e.toString()); } }
//使用抛出处理实现。 public static void div(int a , int b,int[] arr) throws Exception , NullPointerException{ // 声明抛出. if(b==0){ throw new Exception(); // 抛出一个异常对象。
//System.out.println("哈哈,我能执行吗?"); //无法访问到语句。 }else if(arr==null){ throw new NullPointerException(); } int c = a/b; System.out.println("c="+c); } } |
1.3.3自定义异常类
sun给我们提供了很多个异常类,这些异常类都是用于描述java程序中不正常情况的,
但是在现实生活中还有很多不正常的情况,sun并没有使用类进行描述,那么我们如果需要
描述这些不正常情况的时候,我们就需要自定义异常类。
/* 需求:模拟飞Q上线,如果飞Q上线的时候没有插上网线,那么就要抛出一个没有插上网线的异常对象, 如果已经插上了网线,那么正常显示好友列表。
如何自定义一个异常类:自定义一个类继承Exception即可。 */
//自定义一个没有插上网线的异常类 class NoIpException extends Exception {
public NoIpException(String message){ super(message); // 调用了Exceptino带一个参数的构造方法. } }
class Demo9 { public static void main(String[] args) { String ip = "192.168.1.9"; ip = null; try{ feiQ(ip); //调用了一个声明抛出异常类型的方法,调用者必须要处理。 }catch(NoIpException e){ e.printStackTrace(); System.out.println("马上插上网线,别急.."); } }
public static void feiQ(String ip) throws NoIpException { //声明抛出 if(ip==null){ throw new NoIpException("没有插上网线啊,小白!"); } System.out.println("正常显示好友列表.."); } } |
在java程序中释放资源的代码要保证在任何情况下都要执行。
finally的使用前提:必须要配合try块才能使用的,不能单独使用的。
finally块的代码在任何时候都可以执行,除了jvm退出的情况不能执行。
1.4 finally
try块就存在三个格式:
格式 1: try{可能发生异常的代码 }catch(异常类型 变量名){处理异常的代码 } 比较适合用于专门的处理异常的代码,不适合释放资源的代码。 格式2: try{可能发生异常的代码 }catch(异常类型 变量名){处理异常的代码 } finally{ 释放资源的代码} 比较适合用于既要处理异常又有资源释放的代码 格式3: try{可能发生异常的代码 } finally{ 释放资源的代码} 比较适合处理的都是运行时异常且有资源释放的代码。 |
1: 实现方式一:
try{ // 可能发生异常的代码 } catch( 异常类的类型 e ){ // 当发生指定异常的时候的处理代码 }catch...
比较适合用于专门的处理异常的代码,不适合释放资源的代码。
2:实现方式二:
try{ } catch(){} finally{ // 释放资源的代码 }
finally块是程序在正常情况下或异常情况下都会运行的。
比较适合用于既要处理异常又有资源释放的代码
3:实现方式三
try{ }finally{ // 释放资源 }
比较适合处理的都是运行时异常且有资源释放的代码。
4:finally:关键字主要用于释放系统资源。
1:在处理异常的时候该语句块只能有一个。
2:无论程序正常还是异常,都执行finally。
5:finally是否永远都执行?
1:只有一种情况,但是如果JVM退出了System.exit(0),finally就不执行。
2:return都不能停止finally的执行过程。
6:案例使用流
1:使用FileInputStream加载文件。
导包import java.io.FileInputStream;
2:FileNotFoundException
导入包importjava.io.FileNotFoundException;
3:IOException
import java.io.IOException;
public class FinallyDemo { // 本例子使用finally 关闭系统资源。 public static void main(String[] args) {
FileInputStream fin = null; try { System.out.println("1创建io流可能出现异常"); fin = new FileInputStream("aabc.txt"); // 加载硬盘的文本文件到内存,通过流 // System.out.println(fin); } catch (FileNotFoundException e) { System.out.println("2没有找到abc.txt 文件"); System.out.println("3catch 了"); // System.exit(0); // return; } // finally finally { System.out.println("4fianlly执行"); if (fin != null) { // 如果流对象为null 流对象就不存在,没有必要关闭资源 try { fin.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("close 异常"); }
} System.out.println("5finally over"); } System.out.println("6mainover"); } }
// 2:无论程序正常还是异常,都执行finally。但是遇到System.exit(0); jvm退出。 // finally用于必须执行的代码, try{} catch(){}finally{} // try{}finally{}
|