异常的处理
在我们实际开发过程中,我们经常会遇到各种各样的问题,语法错误只是其中的一种而已。而有些问题又只能在运行是才能被发现,比如空指向,下标超出等等,还有些问题是因为用户输入无效的数据等等。
这些问题有可能是用户的错误导致,也有可能是程序员的错误导致,有的是环境导致。而这些问题,我们一般把它们分为两类:异常和错误
错误
错误是程序无法处理的错误,表示运行是应用程序中较为严重的问题,大多数的错误都是与程序员无关,比如内存耗尽等等硬件方面的原因。
异常
注意异常不是错误,它们是不一样的,异常通常可以通过程序员修改代码来的的到解决,而异常有分为,编译时异常Check Exception
和运行时异常Runtime Exception
编译时异常是指不处理的话,将不会通过编译
而运行时异常是指我们在编译时没有异常,到程序运行才出现的异常,比如空指向或者是下标越界等等,这种异常可以在程序中进行捕获处理,也可以不处理。这种异常通常是程序逻辑错误引起的,所以程序应该从逻辑角度尽可能的避免这类异常的发生。
运行时异常的特点是JAVA编译期不会去检查它,在语法上它通过了编译器
异常的处理机制
在java中,有一个专门帮我们处理的问题的类,这个类叫Throwable,它有两个非常重要的子类:Exception(异常)和 Error(错误),它们本身也包含了大量的子类。分别描述了各自不同的异常。因此,程序的异常都是对象,是Throwable子类的实例。
异常一旦发生,JVM(虚拟机)会根据发生异常的类型,产生出该异常的对象。然后把异常对象交给我们的代码取处理。如果我们的代码中没有处理异常。那么它就会结束这个发生异常的方法,带着异常对象返回方法调用处,看调用出有没有进行异常处理,如果还是没有,它再结束方法,再带着异常返回方法调用处,这样一层层的结束掉,退回到main方法,如果main方法还是没有处理,它就会结束掉main,交给JVM自己处理,JVM的处理方案是:打印错误信息,结束整个程序
那么出现异常之后,我们就需要处理,一般的处理手段有3种
1、在异常发生之前处理掉--------这种就完全需要靠经验,习惯了
2、在异常发生之后,捕捉异常,进行处理
3、在异常发生之后,不处理,抛出异常
那怎么进行捕捉和抛出呢?
捕捉异常:
语法: try{………}actch(异常类型){……}
**try{……}**块中是写有可能发生异常的正常逻辑代码,
**actch(异常类型){……}**块中的“( )”是用来书写异常的类型的,判断是否是这个异常类型
而“{……}”是用来书写出现异常后的操作的,它应该根据具体业务来具体实现,可以输错误信息的提示,或者是结束点整个程序。
只要异常类型和actch匹配上,那么JVM就会认为你处理了这个异常,哪怕你是什么都不操作
我们让这段代码试着运行:
try块是书写有可能发生异常的正常逻辑代码,如果没有发生异常,try的代码执行完以后,会自动跳到catch块的外面,执行正常的代码。
如果发生异常,try块剩下的代码将全部被跳过,不执行;JVM就会匹配catch后面的异常类型是否对应发生异常的对象,匹配上则进入actch的语句块执行,执行完毕,跳到catch外面继续往下走,相当于异常已经被处理了。
如果没有匹配上,则方法结束,拿着异常对象返回方法调用处,进入异常传递机制。
使用习惯:每次捕获异常都要加上一个捕获catch(excepion ex )
(只能放在的最后)表示所有异常都可以被处理
finally块
finally{……}
它存在于actch
块的后面,是专用于书写不管是否发生异常都必须要执行的代码,往往是资源的回收,内存的清理,这些善后动作。
finally非常强大,就算有break或return这种改变程序运行流畅的代码也不能阻止他先被执行,再完成流程改变
在代码级别唯一能阻止finally的 只有System.exit(0)
try、catch、finally语句块的执行顺序:
1)当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;
2)当try捕获到异常,catch语句块里没有处理此异常的情况:当try语句块里的某条语句出现异常时,而没有处理此异常的catch语句块时,此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;
3)当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句;
Throwable类中的常用方法
注意:catch关键字后面括号中的Exception类型的参数e。Exception就是try代码块传递给catch代码块的变量类型,e就是变量名。catch代码块中语句"e.getMessage();"用于输出错误性质。通常异常处理常用3个函数来获取异常的有关信息:
getCause():返回抛出异常的原因。如果 cause 不存在或未知,则返回 null。
getMeage():返回异常的消息信息。
printStackTrace():对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。
有时为了简单会忽略掉catch语句后的代码,这样try-catch语句就成了一种摆设,一旦程序在运行过程中出现了异常,就会忽略处理异常,而错误发生的原因很难查找。
抛出异常
throw关键字
在程序中有时候我们会不处理,比如传参错误这些等等,这时候我们需要把异常对象抛出给方法的调用者,让他来进行处理,
语法:方法名后加上throws
方法中: throw 对象名
完整语法:访问修饰符,可选修饰符、返回类型,方法名 frowllys 异常类型
如果抛出的是Exception异常类型,则该方法被声明为抛出所有的异常。多个异常可使用逗号分割。
使用throws关键字将异常抛给调用者后,如果调用者不想处理该异常,可以继续向上抛出,但最终要有能够处理该异常的调用者。
如果抛出的是一个运行时异常对象,那么throw抛出后,编译直接通过
如果抛出的是一个编译时异常对象,那么throw抛出后,编译器还要对这个异常对象进行处理,理方式是要么try -catch,要么在方法声明后加throw。
抛出编译时异常对象的目的是在提醒调用者,本方法可能会产生异常,调用者应该应该进行处理!
要注意的是,throw 抛出的只能够是可抛出类Throwable 或者其子类的实例对象。
Java常见异常
在Java中提供了一些异常用来描述经常发生的错误,对于这些异常,有的需要程序员进行捕获处理或声明抛出,有的是由Java虚拟机自动进行捕获处理。Java中常见的异常类:
1. runtimeException子类:
1、 java.lang.ArrayIndexOutOfBoundsException
数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
2、java.lang.ArithmeticException
算术条件异常。譬如:整数除零等。
3、java.lang.NullPointerException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
4、java.lang.ClassNotFoundException
找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
5、java.lang.NegativeArraySizeException 数组长度为负异常
6、java.lang.ArrayStoreException 数组中包含不兼容的值抛出的异常
7、java.lang.SecurityException 安全性异常
8、java.lang.IllegalArgumentException 非法参数异常
2.IOException
IOException:操作输入流和输出流时可能出现的异常。
EOFException 文件已结束异常
FileNotFoundException 文件未找到异常
3. 其他
ClassCastException 类型转换异常类
ArrayStoreException 数组中包含不兼容的值抛出的异常
SQLException 操作数据库异常类
NoSuchFieldException 字段未找到异常
NoSuchMethodException 方法未找到抛出的异常
NumberFormatException 字符串转换为数字抛出的异常
StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
IllegalAccessException 不允许访问某类异常
InstantiationException 当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常
自定义异常
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
让这个自定义异常类,继承Exception,那么我们的工作就完成了90%
因为Exception具有都所有属性和行为都已经被继承下来了
在方法中通过throw关键字抛出异常对象。
如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
在出现异常方法的调用者中捕获并处理异常。
自定义异常可以自定义各种各样的自定义方法,帮助我们完成辅助效果
最后引用一篇详细的异常处理,大家可以看看:https://blog.csdn.net/youngstar70/article/details/62227032