异常的概念
异常是Java提供的一种识别及响应错误的一致性机制。从而可以达到程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程序健壮性。
定义:异常就是有异于常态,和正常情况不一样,有错误出现。在java中,将程序执行过程中的不正常的情况称之为异常,开发过程中的语法错误和逻辑错误不是异常,发生异常时java会阻止当前方法或作用域的情况。
发生异常的原因
1 用户输入了非法数据
2 要找的文件不存在
3 网络通信中断
4 JVM溢出
出现错误后,会终止程序生命周期执行,此时引入异常后,能够保证程序不会终止,并且还能够把错误信息,进行描述反馈
常见的异常
算术异常
int i=4/0;
System.out.println(i);
异常发生不会执行后续代码
红字代表发生了异常,查看异常源码,所有异常都是exception的子类,exception是throwable的子类。
空指针异常
String name = null;
System.out.println(name.length());
建立一个学生类,有name属性,终端输出length方法
Student st = new Student();
System.out.println(st.getName().length());
数组下标越界异常
建立一个int类型的num数组,有三个元素,赋初值,3个元素,数组索引最大值为2
int[] num = new int[3];
System.out.println(num[3]);
数字格式化异常
String s ="a";
int a = Integer.parseInt(s);
栈异常
public static void main(String[] args) {
a();
}
public static void a(){
a();
}
异常在方法中的体现
new Exception1().aa();
public void aa(){
int[] num = new int[3];
System.out.println(num[3]);
}
两个方法都报错 栈像 子弹夹一样 先进后出,main方法先进栈
在方法中使用异常
public void aa(){
String name = null;
if(name==null) throw new NullPointerException();
System.out.println("不会被执行");
}
Try catch
try{
//try放的是可能发生异常的代码块
int i = 4/0;
System.out.println("没出错了");
}catch (ArithmeticException ex){
//catch 用来捕获异常信息
System.out.println("出错了");
}
练习 定义一个String name 变量,name=null时抛出空指针异常
修改4/1没有出错
//catch 中的异常应匹配出错信息,匹配不到不会跳到catch里
修改catch里的信息为NullPointException ,没有打印出错
多个catch块
演示ctrl +alt +t try catch快捷键
try {
int i=4/0;
String name = null;
System.out.println(name.length());
} catch (NullPointerException e) {
e.printStackTrace();
}catch (ArithmeticException e) {
e.printStackTrace();
}
从上到下依次匹配,可匹配各种异常,注意第一个catch不要写父类的Exception
打印错误信息
try {
int i = 4/0;
} catch (Exception e) {
System.out.println(e.getMessage());
}
错误原因 e.getMessage
打印完整的堆栈信息 e.printStackTrace();
练习 定义一个String name 变量,name=null时抛出异常,打印完整的堆栈信息
异常树
Throwable
所有的异常都是从Throwable继承而来的,是所有所有错误与异常的超类。Throwable包含了其线程创建时线程执行堆栈的快照,它提供了 printStackTrace()等接口用于获取堆栈跟踪数据等信息。
- 而Throwable体系下包含有两个子类,Error(错误)和Exception(异常),它们通常用于指示发生了异常情况。二者都是 Java 异常处理的重要子类,各自都包含大量子类。
Error 网络异常,内存溢出,数据库崩溃,系统错误,严重不应尝试修改,捕获
- 定义:Error类及其子类。程序中无法处理的错误,表示运行应用程序中出现了严重的错误。大多数错误与代码编写者执行的操作无关,而是表示代码运行时 JVM出现的问题。
- 特点:对于所有的编译时期的错误以及系统错误都是通过Error抛出的。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时。通常有如Virtual MachineError (虚拟机运行错误)等。当 JVM不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError(内存溢出错误),还有StackOverflowError(栈溢出错误)等。这些异常发生时,JVM一般会选择线程终止。
- 注意:这些错误是不受检查的,非代码性错误,不可查的。因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。因此,当此类错误发生时,应用程序不应该去处理此类错误。
StackOverFlowException
Exception 异常
Exception 是另外一个非常重要的异常子类。程序本身可以捕获并且可以处理异常。这类异常一旦出现,我们就要对代码进行更正,修复程序。Exception这种异常又分为两类:运行时异常和编译时异常。
RuntimeException 运行时异常 NullPointException ArayyIndexOfExcetion,算术异常应修改逻辑解决
- 定义:RuntimeException 类及其子类异常,如NullPointerException (空指针异常)、IndexOutOfBoundsException (下标越界异常)等,表示 JVM在运行期间可能出现的异常。
- 特点:此类异常,Java 编译器不会检查它,属于不受检查的异常。一般是由程序逻辑错误引起的,此类程序应该从逻辑角度尽可能避免这类异常的发生。而当程序中可能出现这类异常,即使没有用try-catch 语句捕获它,也没有用throws 子句声明抛出它,也会编译通过。在程序中可以选择捕获处理,也可以不处理。如果产生运行异常,则需要通过修改代码来进行避免。例如,若会发生除数为零的情况,则需要通过代码避免该情况的发生!
- 注意:RuntimeException 异常会由JVM自动抛出并自动捕获(就算我们没写异常捕获语句运行时也会抛出错误!!),此类异常的出现绝大多数情况是代码本身有问题,应该从逻辑上去解决并改进代码。 这里我们来看下运行时异常是怎样的,这里我想说下,出现异常,不要紧张,把异常的简单类名,拷贝到API中去查。然后看是什么异常。 可以看出,我们的程序逻辑出现错误,所以出现了算术异常。我们只要修改int b = 10就行了,或者b不等于0都可以。 所以遇到异常,我们不用担心。可以先从查看异常类名开始,看是什么异常,看是什么原因,找到我们程序出错的地方并进行修改就可以正常运行了。
- 那我们什么都没有处理,那出现异常时,是谁处理了这个异常呢? 是JVM的默认处理:把异常的名称,原因,位置等信息输出在控制台,但是呢程序就不能继续执行了。
编译异常也称为检查异常 IoException SqlException 报错 ,要求必须处理。
FileReader fr = new FileReader(new File("c:/a.txt"));
处理异常的方式
1.检查异常
try {
FileReader fr = new FileReader(new File("c:/a.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
2.方法申明中抛出
public void readFiled() throws FileNotFoundException {
FileReader fr = new FileReader(new File("c:/a.txt"));
}
throws告诉调用者方法执行过“程中可能会抛出哪些异常”
使用try-catch捕获此异常并进行处理 也叫回避异常
异常转换
catch后进行再次throw
try {
int i = 4/0;
} catch (Exception e) {
throw new NullPointerException();
}
Try catch finnaly
finally 是必须执行的语句块,写在finally中的代码,一定会执行只有一种情况不会执行,就是 System.exit(0) 退出JVM虚拟机因为其执行的特征,所以一般用于关闭资源操作不能单独使用,需要结合try 或者 try..catch..一起使用
try {
int i = 4/1;
} catch (Exception e) {
e.printStackTrace();
} finally {
//不管是否出现异常都会执行
System.out.println("不管是否出现异常都会执行");
//finally通常用于资源释放,关闭连接等行为 ,前面出现的问题
}
异常和方法覆盖
子类重写父类方法要抛出与父类一致的异常或者子异常,或者不抛出异常
子类重写父类方法所抛出的异常不能超过父类的范畴(仅指检查型异常)
class base{
public void a() throws IOException{
}
}
class a extends base{
public void a() throws FileNotFoundException{
}
}
a 类throws后改为抛出SQLException不可以,必须与父类一致
如果要抛出SQLException,父类再加一个SQLException