第十九节(异常的基本概念, 异常的分类, 异常的捕获和处理,自定义异常,方法覆盖与异常)
1: Java 异常处理 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。 异常发生的原因有很多,通常包含以下几大类: 1. 用户输入了非法数据。 2. 要打开的文件不存在。 网络通信时连接中断,或者JVM内存溢出。这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。 要理解Java异常处理是如何工作的,要掌握以下三种类型的异常: 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。 异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的 错误: 错误不是 2:所有的异常类是从java.lang.Exception类继承的子类。 Exception类是Throwable类的子类。除了Exception类外,Throwable还有一个子类Error 。 Java程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。 Error用来指示运行时环境发生的错误。 异常类有两个主要的子类:IOException类和RuntimeException类 3:异常的分类 异常主要分为:错误、一般性异常(受控异常) 、运行期异常(非受控异常) 错误:如果应用程序出现了 Error,那么将无法恢复,只能重新启动应用程序,最典型 的 Error 的异常是:OutOfMemoryError 受控异常:出现了这种异常必须显示的处理,不显示处理 java 程序将无法编译通过 非受控异常: 此种异常可以不用显示的处理,例如被 0 除异常, java 没有要求我们一定 要处理 4:异常的捕获和处理需要采用 try 和 catch 来处理 try 中包含了可能产生异常的代码 1. try 后面是 catch ,catch 可以有一个或多个,catch 中是需要捕获的异常 2. 当 try 中的代码出现异常时, 出现异常下面的代码不会执行, 马上会跳转到相应的 catch 语句块中,如果没有异常不会跳转到 catch 中 3. finally 表示,不管是出现异常,还是没有出现异常,finally 里的代码都执行,finally 和 catch 可以分开使用,但 finally 必须和 try 一块使用 5:getMessage 和 printStackTrace(): 如何取得异常对象的具体信息,常用的方法主要有两种: 1. 取得异常描述信息:getMessage() 2. 取得异常的堆栈信息(比较适合于程序调试阶段) :printStackTrace()
/* 1. 什么是异常 <1> 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的 <2> 在Java中采用“类” 去模拟异常 <3> 类是可以创建对象的c 2. 异常机制的作用是什么? Java 语言为我们提供一种完善的异常处理机制 作用是: 程序发生异常事件的之后,为我们输出详细信息 开发者通过这个信息 就可以对程序进行一些处理,这样使我们的程序变得更加健壮 */ public class ExceptionTest01{ // Java入口 public static void main(String[] args){ int i = 8; int j = 0; /* 编译通过了,但是运行时出现了异常,表示发什么某个异常事件 实质: 程序执行过程中发生了算数异常这个事件,JVM为我们创建了一个ArithmeticException类型的对象 并且这个对象包含了 详细的异常信息,并且JVM会将这个对象中的信息输出到控制台 */ int k = 8/0; // java.lang.ArithmeticException: System.out.println("Ming太帅了 !" + k); } }
/* 异常处理机制 能够使我们的程序变得更加的健壮 */ public class ExceptionTest02{ public static void main(String[] args){ int i = 6; int j = 0; if(j != 0){ int k = i / j; System.out.println(i + "/" + j + "=" + k); } else { System.out.println("除数不能为零 !"); } } }
/* 处理异常的有两种方式: 1. 声明抛出: throws 2. try ... catch */ import java.io.*; public class ExceptionTest03{ //public static void main(String[] args) throws FileNotFoundException { public static void main(String[] args) throws Exception{ // FileInputStream fis = new FileInputStream("C:\\work\\Java\\course\\vip\\JavaSE-Course-Arry\\chapter21\\ExceptionTest01.java"); } } // import java.io.*; public class ExceptionTest04{ public static void main(String[] args) throws FileNotFoundException{ // arry1(); /* 使用 throws 处理异常不是真正处理 而是推卸责任 谁调用我我就抛给谁 上边的arry1如果出现了异常,可以采用 上抛是,给我们的JVM ,JVM遇到了这个异常就会退出JVM */ // 真正处理 try{ arry1(); //FileInputStream fis = new FileInputStream("C:\\worfsdfsfk\\Java\\course\\vip\\JavaSE-Course-Arry\\chapter21\\ExceptionTest01.java"); } catch(FileNotFoundException e){ System.out.println("太棒了 !"); } } public static void arry1() throws FileNotFoundException{ arry2(); } public static void arry2() throws FileNotFoundException{ System.out.println("执行了Arry2"); new FileInputStream("C:\\1.txt"); } //最后输出太棒了 /* 在程序运行过程中产生了 FileNotFoundException类型的异常 JavaJVM 我们创建了一个 FileNotFoundException类型的对象 该对象中携带了下边的错误信息 JVM负责将该对象的信息打印到控制台 并且javaJVM停掉了程序的运行 Exception in thread "main" java.io.FileNotFoundException: C:\1.txt (系统找不到指定的文件。) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(Unknown Source) at java.io.FileInputStream.<init>(Unknown Source) at ExceptionTest04.arry2(ExceptionTest04.java:31) at ExceptionTest04.arry1(ExceptionTest04.java:26) at ExceptionTest04.main(ExceptionTest04.java:9) */ }
import java.io.*; public class ExceptionTest06{ /* 抛出多个异常 public static void main(String[] args) throws FileNotFoundException,IOException{ FileInputStream fis = new FileInputStream("c:/11.txt"); fis.read(); */ /* 直接使用更大的 public static void main(String[] args) throws IOException{ FileInputStream fis = new FileInputStream("c:/11.txt"); fis.read(); } */ public static void main(String[] args){ try{ FileInputStream fis = new FileInputStream("c:/11.txt"); fis.read(); } catch(FileNotFoundException e){ System.out.println("文件没有找到"); System.out.println(e); } catch(IOException e){ System.out.println(e); System.out.println("其他IO的错误异常"); } System.out.println("Ming太帅了 !"); } 最后输出:
文件没有找到
Exception in thread "main" java.io.FileNotFoundException: C:\1.txt (系统找不到指定的文件。) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(Unknown Source) at java.io.FileInputStream.<init>(Unknown Source) at ExceptionTest04.arry2(ExceptionTest04.java:31) at ExceptionTest04.arry1(ExceptionTest04.java:26) at ExceptionTest04.main(ExceptionTest04.java:9)
Ming太帅了 !
}
/* 关于 getMessage 和 printStackTrace 方法的应用 如何取得异常对象的具体信息,常用的方法主要有两种: 1.取得异常描述信息:getMessage(). 2.取得异常的堆栈信息(比较适合于程序调试阶段)printStackTrace(); */ import java.io.*; public class ExceptionTest07{ public static void main(String[] args){ try{ FileInputStream fis = new FileInputStream("c:/11.txt"); }catch(FileNotFoundException e){ // 取得异常的堆栈信息,比较适合于程序调试阶段 e.printStackTrace(); /* java.io.FileNotFoundException: c:\11.txt (系统找不到指定的文件。) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(Unknown Source) at java.io.FileInputStream.<init>(Unknown Source) at ExceptionTest07.main(ExceptionTest07.java:18) c:\11.txt (系统找不到指定的文件。) */ // 取得异常描述信息 String meg = e.getMessage(); System.out.println(meg); //c:\11.txt (系统找不到指定的文件。) } } }
/* finally 语句块 1. finally语句块可以直接和try语句块联用 try... finally ... 2. try ... catch ... finally 也可以 3. 在finally中的代码是一定会执行的 */ import java.io.*; public class ExceptionTest08{ public static void main(String[] args) throws Exception{ /* try{ System.out.println("ABC"); return; }finally{ System.out.println("太帅了!"); } */ /* try{ FileInputStream fis = new FileInputStream("c:/1.txt"); // 这个是不会执行的 System.out.println("Ming就是帅 !"); }finally{ // 总是执行 System.out.println("总是那么帅 !"); } */ // 只要在执行finally语句块之前退出了Jvm,否则 finally语句块会执行 try{ // 退出Java JVM System.exit(0); } finally{ // 不会执行 System.out.println("太爽了!"); } } }
public class ExceptionTest09{ public static void main(String[] args){ int i = arry(); System.out.println(i);//输出为1; } public static int arry(){ int i = 1; try{ return i; } finally{ i++; System.out.println("i = " + i); } /* 执行原理 int i = 1; try{ int temp = i; return temp; }finally{ i++; System.out.println("i = " + i); } */ } }
/* finally语句块 一定会执行,所以通常在程序中为了保证某资源一定会释放 所以一般在finally语句块中释放资源 1. 受控异常:就是编译异常 2. 非受控异常:就是运行时异常 */ import java.io.*; public class ExceptionTest10{ public static void main(String[] args){ // 必须声明在外边 FileInputStream fis = null; try{ fis = new FileInputStream("c:/11.txt"); }catch(FileNotFoundException e){ e.printStackTrace(); }finally{ // 为了保证资源的释放 if(fis != null){ try{ fis.close(); }catch(IOException e){ e.printStackTrace(); } } } } }
/* 自定义异常 */ import java.io.*; public class ExceptionTest12{ public static void main(String[] args){ try{ arry1(8,0); } catch(MyException e){ String myMsg = e.getMessage(); System.out.println("myMsg = " + myMsg); } } private static void arry1(int i,int j) throws MyException{ // 如果是受控异常 必须声明 if(j == 0){ throw new MyException("除数为0"); } int k = i / j; System.out.println("k = " + k); } } // 定义异常 class MyException extends Exception{ public MyException(){ // 调用父类默认的构造函数 super(); } public MyException(String message){ // 手动调用父类的构造方法 super(message); } }