当前位置: 首页 > news >正文

JAVA中的异常

一、简介

1.1 什么是异常

  异常,是对程序在运行过程中遇到的种种不正常的情况的描述。异常在java中用Exception类来描述。如果程序遇到了未经处理的异常,将会导致程序无法编译或者无法继续运行。

1.2 异常的继承体系

 在java中使用类Throwable来描述所有的不正常的情况。

 Throwable有两个子类,Error和Exception。其中Error用于描述发生在JVM级别的错误信息,这些错误无法被处理。Exception用来描述程序在编译或者运行的过程中遇到的异常信息,这些异常一旦处理了,对程序的编译和运行是没有影响的。

1.3 异常的分类

普通的异常发生,将会导致程序无法进行正常的编译。这种异常,称为None-Runtime Exception,非运行时异常,或者称为编译时异常,也有人称之为检查性异常,原因在于该种异常,都是javac编译器能直接检查到的异常。

     -- 编译器javac.exe  在将源文件(*.java)编译成字节码文件(*.class)时,会主动检查代码的语法格式,如果不正确,就不进行编译工作。如果正确了,才会执行编译工作。

而在Exception的子类RuntimeException中,对异常进行了自动的处理,使其可以正常的编译 运行。但是一旦出现未经处理的异常,依然会导致程序无法继续向下执行。这样的异常称为-- Runtime Exception,运行时异常。 这类异常,通常编译器是不做任何检查的,所以也叫非检查性异常。

总之,异常可以分为 运行时异常编译时异常

二、异常的处理

2.1异常处理的语法

try {
   // 将可能会出现异常的代码放到这里执行
   // 一旦try中的代码出现了异常,则从出现异常的位置开始,到try的大括号的扩回,这一段代码就不执行了。
}catch (需要捕获的异常的类型  标识符) {
   // 如果try中的代码出现了异常,并且异常对象的类型和捕获的类型一致 
   // 这里的代码将会执行
   // 一旦一个异常被捕获了,那么这个异常将不再影响程序的编译和执行
}

1. 将可能出异常的代码片段放入try的语句块中, 
2. jvm在运行程序时,如果出现了异常,则从出现异常的位置开始,到try的大括号的扩回,这    一段代码就不执行了。
3. jvm在运行程序时,如果出现了异常,会自动创建一个具体的异常对象
4. catch(需要捕获的异常的类型  标识符){}用于捕获异常操作
5. jvm创建的异常对象如果与catch捕获的异常对象类型匹配(或者向上造型没问题),就会就将地址值赋值给异常类型变量。
6. catch捕获到异常对象后,就会执行对应的{}里的代码。这个异常将不再影响程序的编译和执行
7. catch模块如何处理异常呢? 比如打印异常信息,供程序员查看,然后进行调试,或者继续抛给调用者

public class example1 {
    public static void main(String[] args) {
       int[] age = {1, 2, 3, 4, 5};
       try {
           System.out.println(age[6]);//打印下标是6的元素
       } catch (Exception e) {
           e.printStackTrace();
       }
        System.out.println("程序继续执行")
    }
}

显示数组下标越界异常,并没有影响程序继续向下运行,继续执行打印语句:程序继续执行

2.2 多种异常的处理

 try {
   // 可能出现异常的代码
}catch (异常类型1 标识符) {
   // 针对异常类型1的处理
}catch (异常类型2 标识符) {
   // 针对异常类型2的处理
}catch (异常类型3 标识符) {
   // 针对异常类型3的处理
}
...

需要注意异常的书写顺序。

如果多个catch的异常之间不存在继承关系,也就是同级关系,不需要考虑书写顺序。
如果多个catch的异常之间存在继承关系,则必须子类异常在前,父类异常在后。

如果处理的多种异常没有继承关系,并且处理方式相同,可以简写成如下语法:

try {
   // 可能会出现多种异常的代码
}catch (异常类型1 | 异常类型2 | ... 标识符) {
   // 出现了多种异常之一,都可以被这里捕获
}

public class example1 {
    public static void main(String[] args) {
      try{
          String a=null;
          System.out.println(a.length());
      }catch (NullPointerException |ArrayIndexOutOfBoundsException e){
          e.printStackTrace();
      }
    }
}

 或者使用父类异常处理

try {
   // 可能会出现多种异常的代码
}catch (Exception e) {
   // 处理的代码逻辑都一样,就一种。
}

public class example1 {
    public static void main(String[] args) {
      try{
          String a=null;
          System.out.println(a.length());
      }catch (Exception e){
          e.printStackTrace();
      }
    }
}

 2.3 finally模块

finally用在try后面,或者catch后面,作为异常捕获的结尾。

特点:finally中的语句始终会执行。(无论try中的代码是否出现了异常,这里的代码都会执行)

使用场景:会在finally中做资源释放、流的关闭等操作。

案例1:

public class example2 {
    public static int test1(){
        int i = 1;
        try {
            i++;
            System.out.println("try block, i = "+i);//i为2,逻辑没错误,不执行catch            后代码
        } catch (Exception e) {
            i--;
            System.out.println("catch block i = "+i);
        } finally {
            i = 10;
            System.out.println("finally block i = "+i);//i为10
        }
        return i;//i为10
    }
    public static void main(String[] args){
        int result = test1();
        System.out.println(result);//i为10
    }
}

案例2: 

public class example2 {
        public static int test2 () {
            int i = 1;
            try {
                i++;//i为2
                throw new Exception();//这里抛出了异常,但是没有处理,所以会跳到catch块中
            } catch (Exception e) {
                i--;
                System.out.println("catch block i = " + i);//i为1
            } finally {
                i = 10;
                System.out.println("finally block i = " + i);//i为10
            }
            return i;//i为10
        }
        public static void main (String[]args){
            int result = test2();
            System.out.println(result);//i为10

案例3: 

public class example2 {
    public static int test3(){
        //try 语句块中有 return 语句时的整体执行顺序
        int i = 1;
        try{
            i++;
            System.out.println("try block, i = " + i);//i为2
            return i;//返回值i为2
        } catch (Exception e) {
            i ++;
            System.out.println("catch block i = " + i);
            return i;
        } finally {
            i = 10;
            System.out.println("finally block i = " + i);//i为10
        }
    }
    public static void main(String[] args){
        int result = test3();
        System.out.println(result);//打印返回值的结果i=2
    }
}

案例4: 

public class example2 {
    public static int test4(){
        //finally 语句块中有 return 语句
        int i = 1;
        try {
            i++;
            System.out.println("try block, i = " + i);//i为2
            return i;//返回i的值为2
        } catch (Exception e) {
            i++;
            System.out.println("catch block i = " + i);
            return i;
        } finally {
            i++;
            System.out.println("finally block i = " + i);//i为3
            return i;//返回i的值为3,覆盖了前面的返回值2
        }
    }
    public static void main(String[] args){
        int result = test4();
        System.out.println(result);//打印结果为3
    }
}

三、自定义异常

3.1 为什么自定义异常

如果系统给我们提供的异常类型,已经不能满足我们的需求了,或者不知道用哪个了。此时就需要进行异常的自定义。

3.2 如何自定义异常

  • 继承自Exception类或者RuntimeException类或者异常子类。

  • 继承自Exception类的异常是 编译时异常。

  • 继承自RuntimeException类的异常是运行时异常。

格式如下:

Class 异常名 extends Exception{ //或继承RuntimeException
   public 异常名(){
   }
   public 异常名(String s){ 
      super(s); 
   }
}

案例:

public class example3 {
    public static void main(String[] args) {
        try {
            person p = new person(-1);
        } catch (NoAgeException e) {
            System.out.println(e.getMessage());//打印异常的信息
        }
    }
}
class person{//定义一个person的类
    private int age;
    person(int age) throws NoAgeException {//声明异常
        this.age=age;
        if(age<0||age>200){
            throw new NoAgeException("年龄不合法");//实例化异常对象
        }
    }
}
class NoAgeException extends Exception{//自定义异常,继承Exception,编译时异常
    NoAgeException(String message){
        super(message);
    }
}

3.3throw和throws关键字

throw:

用在程序方法中,表示抛出异常。一个异常对象实例化完成后,没有任何意义,只有当把这个异常抛出之后,这个异常才会生效,具有阻止程序的编译或者运行的意义。

throws:

1. 书写位置:在方法的定义格式中,也就是形参列表的后面。用于声明异常类型。
     修饰词  返回值类型 方法名(形参列表) throws 异常类型名{
     
     }
2. 当我们throw的是RuntimeException类的异常时,不需要throws来声明异常类型, 声明没有意义,JVM运行程序才能知道。
3. 当我们throw的是Exception异常时,必须使用throws来声明异常类型,用来告知  谁调用这个方法,谁处理异常。

public class example2 {

    public static void main(String[] args){
        try {
            test();//main()方法调用了test()方法,所以要处理异常
        } catch (Exception e) {
           System.out.println(e.getMessage());//打印异常对象的信息
        }
    }
    public static String test() throws Exception {//异常声明,谁调用这个方法谁处理异常
        try {
            int[] a = {1, 2, 3};
            a[10] = 10;//给下标为10的元素赋值为10,但是数组下标只到2,出现异常
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new Exception("数组越界了");//执行这行代码,实例化了一个异常对象
        }
        return "-----";
    }
}

相关文章:

  • 俄罗斯方块游戏完整代码示例
  • 从SSM到S4
  • C++--封装
  • uniapp 使用v-html在微信小程序中渲染成rich-text如何显示文本溢出省略
  • 数据库加密全解析:从传输到存储的安全实践
  • 计算机硬件组成+vmware虚拟机使用
  • #第十二题
  • window中git bash使用conda命令
  • 数据分析、商业智能、业务分析三者之间的关系
  • 计算机毕业设计hadoop+spark旅游景点推荐 旅游推荐系统 旅游可视化 旅游爬虫 景区客流量预测 旅游大数据 大数据毕业设计
  • MapReduce的工作原理及其在大数据处理中的应用
  • 多层代理模式解析Invocation
  • 重构测试项目为spring+springMVC+Mybatis框架
  • Debezium同步之如何同步GIS数据
  • 李代数和李群的转化方法
  • 计算机专业知识【软件开发中的常用图表:E - R图、HIPO、DFD、N - S、PAD详解】
  • STM32 HAL库USART串口中断编程:演示数据丢失
  • AI 百炼成神:线性回归,预测房价
  • ESP32 ESP-IDF TFT-LCD(ST7735 128x160) LVGL基本配置和使用
  • PID控制学习
  • 让其他公司做网站应注意什么/百度信息流推广技巧
  • 福田网站网页设计/网站推广服务报价表
  • 盐城网站定制/友情链接是啥意思
  • 福田网站建设哪家便宜/软文推广的100个范例
  • 域名访问网站应该怎么做/长沙有实力seo优化
  • 郑州郑州网站建设河南做网站公司/千万不要学网络营销