复习java基础,异常类和异常处理
一、异常分类
java的一切异常和错误都是继承Throwable,Throwable下两个子类Error和Exception,Error一般为系统内部错误,我们处理不了,由系统处理。我们关注的是Exception,Exception是我们能够处理的异常,这些异常往往是由于我们编码出问题或者操作引起的异常。
Exception下有很多子异常,可以分为两大类RuntimeException(运行时异常 也叫非检查异常)和其他各种异常(非运行异常 也叫检查异常)。
RuntimeExcption 异常(运行时异常)通常有以下几种:
- 空指针异常(NullPointerException)
- 类型转换异常(ClassCastException)
- 数组下标越界异常(ArrayIndexOutOfBoundException)
- 算术异常(ArithmeticException)
…
一般来说,RuntimeException 一般都是代码有问题,逻辑有错。这些异常在编译时并不会报错,可以捕获,也可以不捕获的异常,会由JVM(java虚拟机)自动抛出自动捕获。
编译时异常,一般都是IOException或SQLException等
- 打开一个不存在的文件
- 没有找到具有指定名称的类
- 操作文件异常
- 连接错误
- sql错误
…
非运行时异常,是检查异常。受查异常是编译器要求必须处理的异常,必须使用 try catch 处理,或者向上抛出,给上层处理。否则编译时会报错。(强调区别)
二、抛出异常
异常抛出
异常抛出的语法是
throw new 异常名();
在add方法里,抛出了个RuntimeException的子类NullPointerException
package test;
public class ThrowTest {
public static void main(String[] args) {
add(1,null);//调用方法
}
public static Integer add(Integer a,Integer b){
if(a == null || b == null){//抛出异常
throw new NullPointerException("相加的Interger值不能为空");
}else{
return a + b;
}
}
}
运行结果
Exception in thread "main" java.lang.NullPointerException: 相加的Interger值不能为空
at test.ThrowTest.add(ThrowTest.java:15)
at test.ThrowTest.main(ThrowTest.java:8)
NullPointerException是运行时异常,注意没有在方法头抛出也没有去捕获,能编译通过没报错,上面说过运行时异常可捕获和不捕获,运行时JVM自动抛出和捕获。
throws 声明异常
throws 用于声明异常,表示该方法可能会抛出的异常。如果声明的异常中包括 checked 异常(受查异常),那么调用者必须处理该异常或者使用 throws 继续向上抛出。throws 位于方法体前,多个异常使用,分割。
三、异常捕获
捕获异常的语法是
try{
//可能抛出异常的代码块
}catch(Exception e){//捕获异常
}fianlly{
}
try是必有的,而catch和fianlly是可选的,catch是捕获异常后的处理,fianlly里是不管异常是否发生都会执行里面的语句
package test;
public class ThrowTest {
public static void main(String[] args) {
try{
int num = add(1,null);//调用方法
System.out.println(num);
}catch(NullPointerException e){
}
}
public static Integer add(Integer a,Integer b) throws NullPointerException{//方法头声明抛出的异常
if(a == null || b == null){//抛出异常
throw new NullPointerException("相加的Interger值不能为空");
}else{
return a + b;
}
}
}
1.上面我用catch捕获了异常但不做处理
运行后,控制台不报异常,没有输出,因为我们捕获了却不做处理
2.如果catch里加了输出
catch(NullPointerException e){
System.out.println("ERROR加法出了问题:"+e.getMessage());
}
运行后控制台的输出:
加法出了问题:相加的Interger值不能为空
3.如果catch里加了e.printStackTrace();
catch(NullPointerException e){
System.out.println("ERROR加法出了问题:"+e.getMessage());
e.printStackTrace();
}
控制台输出
ERROR加法出了问题:相加的Interger值不能为空
java.lang.NullPointerException: 相加的Interger值不能为空
at test.ThrowTest.add(ThrowTest.java:18)
at test.ThrowTest.main(ThrowTest.java:7)
可见 e.printStackTrace();的作用是输出异常的轨迹,这异常堆栈轨迹,方便我们找到异常。
一个try可以有多个catch
public static void main(String[] args) {
try{//捕获处理
TestTwo();
}catch(NullPointerException e){
System.out.println("捕获了空子针异常");
e.printStackTrace();
}catch(RuntimeException e){
System.out.println("捕获了运行时异常");
e.printStackTrace();
}catch(IOException e){
System.out.println("捕获了IO异常");
e.printStackTrace();
}catch(Exception e){
System.out.println("捕获了未知异常");
e.printStackTrace();
}
}
注意:
1.当匹配到对应的异常后,后面的异常将不再进行匹配。
2.而且也不要求完全匹配,如果是子类的异常,其父类可以到匹配,像Exception可以匹配任何异常。
所以如果多个catch,有子父异常,子异常一定要放在前面,像先catch NullPointerException 再catch RuntimeException, 否则会报错。(原因也很简单,如果父类 RuntimeException在前面,他会先匹配了,其子类在后面永远也执行不到)
如果抛出的是受检查异常(非运行异常)
必须try,catch处理,如果不处理则要继续抛出由上层处理,否则报错(强调和运行时异常的区别)
package test;
import java.io.IOException;
public class ThrowTest {
public static void main(String[] args) {
try{//捕获处理
TestTwo();
}catch(Exception e){
e.printStackTrace();
}
}
//方法TestTwo调用方法testOne,受检查异常要捕获异常或者继续抛出交由上层处理,否则会报错
public static void TestTwo()throws IOException{ //继续抛出
TestOne();
}
//方法testOne声明了可能抛出的异常
public static void TestOne()throws IOException,NullPointerException{
if( 1 == 1)
throw new IOException(); //抛出了受检查异常
else{
throw new NullPointerException();
}
}
}
四、自定义异常
如果在开发自己的项目,不免要自定义异常类型。
简单定义一个异常,继承RuntimeException,当然也可以继承Exception.但是在spring里的事务只支持对RuntimeException的回滚
package test;
public class IsNullException extends RuntimeException{
public IsNullException() {
super();
}
public IsNullException(String message) {
super(message);
}
}
抛出并捕获
package test;
public class ThrowTest {
public static void main(String[] args) {
try{//捕获处理
Add(1,null) ;
}catch(Exception e){//捕获异常
e.printStackTrace();
}
}
public static Integer Add (Integer a,Integer b){
if(a == null || b == null){
throw new IsNullException("加数不能为空");//抛出自定义异常
}
else{
return a+b;
}
}
}
还可以依靠异常处理来做很多东西
。。。