Java 异常分类及处理

1.异常及代码不正常执行,异常类Throwable 创建一个异常对象并抛出 就是异常的产生。此时Java会中断

  1.1 Errow类 一般为代码缺陷 不应该被异常处理

  1.2 Exception 分为 编译异常 和 运行异常 (都需要修复)

  1.3Throwable 中长用的方法

   例1 

public void printStackTrace() // 打印异常的详细信息 包含 ①异常类型 ②异常原因 ③异常出现的位置
public String getMessage()   // 打印异常原因 (注意返回值是字符串)

public class ExceptionTest {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2};
        ArrayTool.print(arr, 2);
    }
}
class ArrayTool{
    public static void print(int[] arr,int index) {
        System.out.println(arr[index]); //1
    }
}
 
执行过程
  ① 数组索引值2的值没有找到,运行发生异常,JVM识别异常为 java.lang.ArrayIndexOutOfBoundsException (数组越界)
    这个异常本身存在 描述内容包括 异常名称 异常内容 异常的产生位置.Java将这些信息直接封装到异常对象里 new ArrayIndexOutOfBoundsException(2)
  ② throw
new ArrayIndexOutOfBoundsException(2) 产生异常对象
  ③ JVM 将异常对象抛给调用者main()方法
④ main()方法接受到了数组索引越界异常对象。由于没有处理异常 main()方法直接抛给调用者JVM.当JVM收到异常后 将异常对象中的 名称 内容 位置 显示出来 同时让程序停止
 
 

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at com.baidu.www2.ArrayTool.print(ExceptionTest.java:11)
at com.baidu.www2.ExceptionTest.main(ExceptionTest.java:6)


2.异常的处理

  2.1try

  2.2catch

  2.3finally

  

作者:一只Tom猫
链接:https://zhuanlan.zhihu.com/p/90223112
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

public class TryCatchDemo {
    public static void main(String[] args) {
        try {// 当产生异常时,必须有处理方式。要么捕获,要么声明。
            read("b.txt");
        } catch (FileNotFoundException e) {// 括号中需要定义什么呢?
              //try中抛出的是什么异常,在括号中就定义什么异常类型
            System.out.println(e);
        }
        System.out.println("over");
    }
    /*
     *
     * 我们 当前的这个方法中 有异常  有编译期异常
     */
    public static void read(String path) throws FileNotFoundException {
        if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
            // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
            throw new FileNotFoundException("文件不存在");
        }
    }
}

  

2.5 finally 代码块与return语句

还有个特别重要的点就是在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行,另外finally语句中也可以有return语句,但是尽量避免有return语句(会报警告)

  2.4throw

    抛出异常  throw new [异常类型("内容输出")]

throw new ArrayIndexOutOfBoundsException("索引越界");
public class ExceptionTest {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2};
        ArrayTool.print(arr, 2);
    }
}
class ArrayTool{
    public static void print(int[] arr,int index) {
        if(index<0||index>=arr.length) {
            throw new ArrayIndexOutOfBoundsException("索引越界");
        }
        System.out.println(arr[index]);
    }
}

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 索引越界
at com.baidu.www2.ArrayTool.print(ExceptionTest.java:12)
at com.baidu.www2.ExceptionTest.main(ExceptionTest.java:6) (可以与例1对比)


 

  2.5throws

   异常产生 我们已经可以使用throw将异常抛出,也将问题返回给了方法的调用者。那么对于调用者来说,怎么处理?一种是进行捕获处理,另一种就是继续将问题声明出去m使用throws声明处理

    关键字throws运用于方法声明之上,throws格式为修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ },用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).

public class ExceptionTest {
    public static void main(String[] args) throws IOException {
        read("a.txt");
    }

    // 如果定义功能时有问题发生需要报告给调用者。可以通过在方法上使用throws关键字进行声明
    public static void read(String path) throws FileNotFoundException,IOException  {
        if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
            // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
            throw new FileNotFoundException("文件不存在");
        }
        if (!path.equals("b.txt")) {
            throw new IOException();
        }
    }
}

  throw

  • 表示方法内抛出某种异常对象
  • 如果异常对象是非 RuntimeException 则需要在方法申明时加上该异常的抛出 即需要加上 throws 语句 或者 在方法体内 try catch 处理该异常,否则编译报错
  • 执行到 throw 语句则后面的语句块不再执行

  throws

   方法的定义上使用 throws 表示这个方法可能抛出某种异常 2、需要由方法的调用者进行异常处理

2.6 异常注意事项

多个异常使用捕获又该如何处理呢?

  • 多个异常分别处理。
  • 多个异常一次捕获,多次处理。
  • 多个异常一次捕获一次处理。

一般我们是使用一次捕获多次处理方式,格式如下:

try{
     编写可能会出现异常的代码
}catch(异常类型A  e){  当try中出现A类型异常,就用该catch来捕获.
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}catch(异常类型B  e){  当try中出现B类型异常,就用该catch来捕获.
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}

注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

异常注意小结

  • 运行时异常被抛出可以不处理。即不捕获也不声明抛出。
  • 如果finallyreturn语句,永远返回finally中的结果,避免该情况. 上面也提到过
  • 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
  • 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出

自定义异常

// 自定义异常类
// 1.继承Exception类
// 2.创建版本号 static final long serialVersionUID = -3387516993124229948L;
// 3.创造构造函数
public class EcDef extends Exception {
    static final long serialVersionUID = -3387516993124229948L;

    public EcDef() {
        super();
        // TODO Auto-generated constructor stub
    }

    public EcDef(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }

}
public class EcmDef {
    public static void main(String[] args) {
        try {
            int i = Integer.parseInt(args[0]);
            int j = Integer.parseInt(args[1]);
            int result = ecm(i, j);
            System.out.println(result);
        } catch (NumberFormatException e) {
            System.out.println("数据类型不一致");
            e.printStackTrace();
            System.out.println(e.getMessage());
        } catch (ArrayIndexOutOfBoundsException e) {
//            e.printStackTrace();
            System.out.println("缺少命令行参数");
        }catch (ArithmeticException e) {
            System.out.println("除以0的异常");
//            e.printStackTrace();
        }catch (EcDef e) {
            System.out.println(e.getMessage());
        }
        
    }

    public static int ecm(int i, int j) throws EcDef{
        if (i < 0 || j < 0) {
            throw new EcDef("分母或分子为负数了!");
        }
        return i / j;
    }
}

 

 

原文链接 https://juejin.im/post/5dc0ba1c5188255f77580427

 

posted @ 2020-04-03 17:59  追忆枉然  阅读(345)  评论(0)    收藏  举报