一、知识点
21.异常
21.1.异常结构
异常:程序在运行过程中出现了问题,导致程序不能正确结束
异常的层次结构:
异常分为两种类型:Throwable是所有异常的父类,它的子类是Exception,Error,
在程序中只负责Exception ,Error为程序外部错误,程序本身不可控制
Exception 分为两种类型:
运行异常RuntimeException 所有运行时异常都是RuntimeException的子类
常见的运行时异常有:ArrayIndexOutOfBoundsException 数组下标越界异常,
NullPointerException 空指针异常,ArithmeticException 算术为0异常
,NumberFormatException 数字格式异常,ClassCastException 类型转换异常
运行时异常不是需要必须处理的
检查异常 CheckedException所有的检查异常都是Exception的子类
常见的检查异常
FileNotFoundException 文件找不到异常 IOException 文件流异常
,ClassNotFoundException 类找不到异常 SQLException 数据库异常
检查异常是需要必须处理的
21.2.定位异常抛出的位置
寻找第一句自己编写的代码
21.3.异常的处理方法
异常处理只能保证程序可以正常结束,并不能保证程序能够获取正确的结果.
异常处理的方法一共有两种:
声明异常throws 和 throw 抛出异常
try catch finally 捕获异常
第一种处理throw 和throws 抛出异常(最常用,只要是自定义的方法就要使用throws去声明异常的类型)
异常处理的第一种方式: throw ,throws 抛出异常
// throw 抛出异常,需要抛出一个异常对象,在方法中
// throws 声明异常,在方法定义的时候,当方法中抛出的是运行时异常该方法可以声明异常也可以不声明异常
// 如果方法中抛出了检查异常,则必须在方法中做出异常的声明
// 如果方法中抛出了多个检查异常 需要在声明的时候可以直接声明多个异常也可以直接声明一个父类异常(Exception)
//异常处理的第一种方式: throw ,throws 抛出异常
// throw 抛出异常,需要抛出一个异常对象,在方法中
// throws 声明异常,在方法定义的时候,当方法中抛出的是运行时异常该方法可以声明异常也可以不声明异常
// 如果方法中抛出了检查异常,则必须在方法中做出异常的声明
// 如果方法中抛出了多个检查异常 需要在声明的时候可以直接声明多个异常也可以直接声明一个父类异常(Exception)
public static void testThrowRuntimeExcetion() throws Exception
// throws SQLException ,FileNotFoundException // throws NullPointerException
{
Person p = null;
if (p == null)
throw new NullPointerException("p 为空"); //抛出一个运行时异常,方法可以声明异常也可以不声明异常
int i = 4;
int j = 5;
if (j == 0)
//抛出了第一个检查异常,方法必须声明对应的检查异常
throw new SQLException("j不能为0");
if (i == 0)
//抛出了第二个检查异常,方法的声明要么都声明,要么直接声明一个父类
throw new FileNotFoundException("i不能为0");
p.eat();
}
异常的第二种处理方式:try catch finally
//异常处理的第二种方法:try 捕获异常 catch 处理异常 finally 必须执行
//try{ 程序代码; }catch(Exception ex){ 1:抛出,2:打印异常信息,3:记录日志信息 }finally{ 释放资源 }
//其中catch是可以省略的,finally也是可以省略的但两不能同时省略(try 不能单独存在)
//finally 只能出现一次,catch可以出现多次
//如果catch出现了多重,则需要通过多重catch处理每一个异常
//(在多重catch中,父类的异常(Exception) 必须放在最后一个)
//异常处理的时候方法返回值问题
//如果在方法中存在try{} catch finally ,且finally中存在return 则方法不论是否存在异常都会返回finally中值
//如果try存在return ,catch中存在return try外面不能出现return 子句
//不论方法执行是否存在异常,都会返回i+j的值
public static int getResult(int i,int j){
try{
int k = i /j;
return k;
}catch(Exception ex){
ex.printStackTrace();
return 22;
}finally{
return i+j;
}
//return 10; //此句代码错误,永远不可能执行
}
在调用方法的时候
//方法中抛出的是运行时异常 调用的时候可以不处理
//如果调用的方法声明了编译异常,则需要显示处理
//如果调用的方法声明了多个编译异常,则需要通过多重catch处理每一个异常
//(在多重catch中,父类的异常(Exception) 必须放在最后一个)
一般情况下,在自定义方法中必须要抛出异常,不要自己处理异常,如果需要处理异常,也需要处理完毕以后抛出异常信息
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try{
int resu = testException(3,9);
System.out.println("结果是:" + resu);
}catch(Exception ex){
ex.printStackTrace();
}
}
public static int testException(int num1,int num2) throws NullPointerException,Exception{
try{
int resu = num1/num2;
System.out.println("程序正常");
return resu;
}catch(NullPointerException ex1){
throw ex1;
}catch(Exception ex){
throw ex;
}
finally{
System.out.println("这是finally中的代码");
return 8;
}
}
方法定义的时候声明了多个异常
public static void testTry() throws ClassNotFoundException,SQLException,IOException{
System.out.println("测试方法");
int[] nums = {2,3,4,5};
if(nums == null)
throw new NullPointerException("数组为空"); //方法中抛出的是运行时异常
if(nums.length >5)
throw new ClassNotFoundException("太大了"); //方法中抛出了编译异常,则必须在方法中声明
if(nums[2]>20)
throw new SQLException("数字不正确"); //方法中抛出了编译异常2
if(nums[3]>20)
throw new IOException("数字不正确"); //方法中抛出了编译异常2
}
方法调用的时候可以有多种处理方法
try {
testTry();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}catch(SQLException ex){
ex.printStackTrace();
}catch(IOException ex){
ex.printStackTrace();
}
//第四种 和第一种相同
try {
testTry();
}catch (ClassNotFoundException |SQLException |IOException e) {
e.printStackTrace();
}
//第二种方法(在多重catch中,父类的异常(Exception) 必须放在最后一个)
try {
testTry();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}catch(Exception ex){
ex.printStackTrace();
}
//第三种方法最常用(可以处理所有的异常:运行时异常和编译异常都可以)
try {
testTry();
}catch(Exception ex){
ex.printStackTrace();
}
21.4.自定义异常
如果定义一个检查异常只需要继承 Exception就可以
如果定义一个运行时异常需要继承RuntimeException就可以