Java异常处理--异常处理概述与常见异常举例

2024-01-09 11:29:45

一、异常概述

1- 什么是生活的异常

男主角小明每天开车上班,正常车程1小时。但是,e4不出意外的话,可能会出现意外。
image.png

出现意外,即为异常情况。我们会做相应的处理。如果不处理,到不了公司。处理完了,就可以正常开车去公司。
image.png

2- 什么是程序的异常

在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:客户输入数据的格式问题读取文件是否存在网络是否始终保持通畅等等。

  • 异常 :指的是程序在执行过程中,出现的非正常情况,如果不处理最终会导致JVM的非正常停止。

异常指的并不是语法错误和逻辑错误。

语法错了,编译不通过,不会产生字节码文件,根本不能运行。

代码逻辑错误,只是没有得到想要的结果,例如:求a与b的和,你写成了a-b

3- 异常的抛出机制

Java中是如何表示不同的异常情况,又是如何让程序员得知,并处理异常的呢?

Java中把不同的异常用不同的类表示,一旦发生某种异常,就创建该异常类型的对象,并且抛出(throw)。然后程序员可以捕获(catch)到这个异常对象,并处理;如果没有捕获(catch)这个异常对象,那么这个异常对象将会导致程序终止。

举例:

运行下面的程序,程序会产生一个数组角标越界异常ArrayIndexOfBoundsException。我们通过图解来解析下异常产生和抛出的过程。

public class ArrayTools {
    // 对给定的数组通过给定的角标获取元素。
    public static int getElement(int[] arr, int index) {
        int element = arr[index];
        return element;
    }
}

测试类

public class ExceptionDemo {
    public static void main(String[] args) {
        int[] arr = { 34, 12, 67 };
        intnum = ArrayTools.getElement(arr, 4)
        System.out.println("num=" + num);
        System.out.println("over");
    }
}

上述程序执行过程图解:

image.png

4- 如何对待异常

对于程序出现的异常,一般有两种解决方法:一是遇到错误就终止程序的运行。另一种方法是程序员在编写程序时,就充分考虑到各种可能发生的异常和错误,极力预防和避免。实在无法避免的,要编写相应的代码进行异常的检测、以及异常的处理,保证代码的健壮性

二、Java异常体系

1- Throwable

java.lang.Throwable 类是Java程序执行过程中发生的异常事件对应的类的根父类

Throwable类是异常的根父类,它继承于Object类。

Throwable中的常用方法:

  • public void printStackTrace():打印异常的详细信息。
    包含了异常的类型、异常的原因、异常出现的位置、在开发和调试阶段都得使用printStackTrace。
  • public String getMessage():获取发生异常的原因。

2- Error 和 Exception

Throwable可分为两类:Error错误)和Exception异常)。分别对应着java.lang.Errorjava.lang.Exception两个类。

看一下API:

image.png

Throwable不做过多关注,更多的是它的这两个子类。

1、Error

1.1 介绍

Error:Java虚拟机无法解决的严重问题。

如:JVM系统内部错误、资源耗尽等严重情况。

一般不编写针对性的代码进行处理。(如果出现Error问题,就回去改代码,后面说的try方式对它无效)

  • 例如:StackOverflowError(栈内存溢出)和OutOfMemoryError(堆内存溢出,简称OOM)。

看一下API:

image.png

1.2 举例

【举例1】

StackOverflowError(栈内存溢出)

public class ErrorTest {
    public static void main(String[] args) {
        //举例1:栈内存溢出StackOverflowError
        main(args); //递归--main方法中调用main方法
    }
}

🍻分析

main(args);

递归–main方法中调用main方法,每调用一次main方法,就进去一个栈帧,在栈空间有限的情况下,一直往里面放栈帧,总会满的。

🗃?输出

栈内存溢出:

image.png


【举例2】

OutOfMemoryError(堆内存溢出,简称OOM)

public class ErrorTest {
    public static void main(String[] args) {
		//举例2:堆内存溢出 OutOfMemoryError (简称OOM)
        byte[] arr=new byte[1024*1024*100]; //100mb
    }
}

🍻分析

new出来的结构在堆空间中呈现,若此时堆空间不足100mb,就会将堆空间占满,这时候堆空间就会报一个溢出异常。

现在我们做一个操作,“运行”->“编辑配置”:

image.png

然后针对当前模块,“修改选项”->“添加VM选项”:

image.png

就是虚拟机参数,将它设置为-Xms10m -Xmx10m ,前面的-Xms10m表示堆空间初始化的大小,后面的 -Xmx10m表示最大的堆空间大小。就是固定下来堆空间大小为10ms。如下:

image.png

🗃?输出

byte[] arr=new byte[1024*1024*100]; //100mb

显然此时100ms不够,运行一下就会有一个堆空间溢出

image.png

看见后缀是Error的,其实都是一个错误。

2、Exception

2.1 介绍

Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,需要使用针对性的代码进行处理,使程序继续运行。否则一旦发生异常,程序也会挂掉。(这一章要学习异常处理 ,实际上针对的是这个Exception,而Error处理不了)

看一下API:

image.png

例如:

  • 空指针访问
  • 试图读取不存在的文件
  • 网络连接中断
  • 数组角标越界

说明:

  1. 无论是Error还是Exception,还有很多子类,异常的类型非常丰富。当代码运行出现异常时,特别是我们不熟悉的异常时,不要紧张,把异常的简单类名,拷贝到API中去查去认识它即可。
  2. 我们本章讲的异常处理,其实针对的就是Exception。

image.png

2.2 编译时异常和运行时异常

Java程序的执行分为编译时过程运行时过程。有的错误只有在运行时才会发生。比如:除数为0,数组下标越界等。
image.png

因此,根据异常可能出现的阶段,可以将异常分为:

  • 编译时期异常(即checked异常、受检异常):在代码编译阶段,编译器就能明确警示当前代码可能发生(不是一定发生)xx异常,并明确督促程序员提前编写处理它的代码。如果程序员没有编写对应的异常处理代码,则编译器就会直接判定编译失败,从而不能生成字节码文件。通常,这类异常的发生不是由程序员的代码引起的,或者不是靠加简单判断就可以避免的,例如:FileNotFoundException(文件找不到异常)。
  • 运行时期异常(即runtime异常、unchecked异常、非受检异常):在代码编译阶段,编译器完全不做任何检查,无论该异常是否会发生,编译器都不给出任何提示。只有等代码运行起来并确实发生了xx异常,它才能被发现。通常,这类异常是由程序员的代码编写不当引起的,只要稍加判断,或者细心检查就可以避免。
    • java.lang.RuntimeException类及它的子类都是运行时异常。比如:ArrayIndexOutOfBoundsException数组下标越界异常,ClassCastException类型转换异常。

运行时异常:通常编译的时候不报错,相当于编译的时候将它放过去了,就是没有检查它,即:非受检异常。

编译时异常:编译的时候就会报错,一上来就检查它了,即:受检异常。

?在API中,怎么看哪个是编译时异常还是运行时异常呢?

这个地方,除了RuntimeException,其他都是编译时异常。如下:

image.png

点开它,里面都是运行时异常RuntimeException,如下:

image.png

我们需要熟悉一下常见的异常都有哪些,太多了也学不过来。

image.png

Error有时也可以归为“非受检异常”,因为编译时不报错,看上面蓝色方块。

3- Java异常体系结构

1、体系结构

java.lang.Throwable:异常体系的根父类

  • java.lang.Error:错误

    • Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理
      ? |-----StackOverflowError (栈内存溢出)
      ? |-----OutOfMemoryError (堆内存溢出,简称OOM)
  • java.lang.Exception:异常

    • 我们可以编写针对性的代码进行处理

    • 编译时异常:(受检异常) 在执行javac.exe命令时,出现的异常。
      |----- ClassNotFoundException(类找不到异常)
      |----- FileNotFoundException(文件找不到异常)
      |----- IOException(输入输出异常)

    • 运行时异常:(非受检异常) 在执行java.exe命令时,出现的异常。
      |---- ArrayIndexOutOfBoundsException (数组越界–用非法索引访问数组时抛出的异常)
      |---- NullPointerException (空指针异常)
      |---- ClassCastException (类转换异常)
      |---- NumberFormatException (数据格式化异常)
      |---- InputMismatchException (输入类型不一致)
      |---- ArithmeticException (算术异常)

2、运行时异常举例

  • ArrayIndexOutOfBoundsException (数组越界–用非法索引访问数组时抛出的异常)
  • NullPointerException (空指针异常)
  • ClassCastException (类转换异常)
  • NumberFormatException (数据格式化异常)
  • InputMismatchException (输入类型不一致)
  • ArithmeticException (算术异常)
2.1 ArrayIndexOutOfBoundsException

🗳?ArrayIndexOutOfBoundsException数组角标越界

🌱代码

package yuyi01;

import org.junit.Test;

public class ExceptionTest {
    @Test
    public void test1(){
        //数组角标越界 ArrayIndexOutOfBoundsException
        int[] arr=new int[10];
        System.out.println(arr[10]);
    }
}

🍺异常

image.png

2.2 NullPointerException

🗳?NullPointerException空指针异常

🌱代码1

package yuyi01;

import org.junit.Test;

public class ExceptionTest {
    @Test
    public void test2(){
        //空指针异常 NullPointerException
        String str="hello";
        str=null;   //指针指向为空
        System.out.println(str.toString());
    }
}

🍺异常

image.png


🌱代码2–一维数组

package yuyi01;

import org.junit.Test;

public class ExceptionTest {
    @Test
    public void test3(){
        //空指针异常 NullPointerException
        int[] arr=new int[10];  //一维数组
        arr=null;
        System.out.println(arr[0]);
    }
}

🍺异常

image.png


🌱代码3–二维数组

package yuyi01;

import org.junit.Test;

public class ExceptionTest {
    @Test
    public void test4(){
        //空指针异常 NullPointerException
        int[][] arr1=new int[10][]; //二维数组
        System.out.println(arr1[0][0]);
    }
}

🍺异常

image.png

只要对象指向的没有实体,调一个方法或者属性都算空指针。

2.3 ClassCastException

🗳?ClassCastException类转换异常

🌱代码

package yuyi01;

import org.junit.Test;

import java.util.Date;

public class ExceptionTest {

    @Test
    public void test5(){
        //类转换异常 ClassCastException
        Object obj=new String();    //new一个String对象,将它赋值给Object类
        //String str=(String) obj;    //这里不会出现强转异常
        Date date=(Date) obj;   //转换为别的类型就不行了
    }
}

🍺异常

image.png

父类引用指向的对象的类型是子类的时候才可以强制类型转换。

而Date和String算是平等的关系,都继承于Object,它们是兄弟关系,不能强转。

2.4 NumberFormatException

🗳?NumberFormatException数据格式化异常

🌱代码

package yuyi01;

import org.junit.Test;

public class ExceptionTest {
    @Test
    public void test6(){
        //NumberFormatException 数据格式化异常
        String str1="123";
        int i1 = Integer.parseInt(str1);  //可以将String类型的“123”转化为int类型的123

        String str2="abc";
        int i2 = Integer.parseInt(str2);    //不可以转换,会报错

        System.out.println(i1);
        System.out.println(i2);
    }
}

🍺异常

image.png

2.5 InputMismatchException

🗳?InputMismatchException输入类型不一致

🌱代码

package yuyi01;

import org.junit.Test;

import java.util.Scanner;

public class ExceptionTest {

    @Test
    public void test7(){
        //InputMismatchException 输入类型不一致
        Scanner scanner=new Scanner(System.in);
        int num= scanner.nextInt(); //若输入的不是int类型,则会报错
        System.out.println(num);
    }
}

🍺异常

image.png

2.6 ArithmeticException

🗳?ArithmeticException算术异常

🌱代码

package yuyi01;

import org.junit.Test;

public class ExceptionTest {
    @Test
    public void test8(){
        //ArithmeticException 算术异常
        int num=10;
        System.out.println(num/0);  //编译的时候不报错,运行的时候报错
    }
}

🍺异常

image.png

3、编译时异常举例

  • ClassNotFoundException(类找不到异常)
  • FileNotFoundException(文件找不到异常)
  • IOException(输入输出异常)
3.1 ClassNotFoundException

🗳?ClassNotFoundException类找不到异常

🌱代码

package yuyi01;

import org.junit.Test;

public class ExceptionTest {

    @Test
    public void test9(){ 
        //ClassNotFoundException 类找不到异常
        Class clz=Class.forName("java.lang.String");  //反射
    }
}

🍺异常

image.png

目前只能考虑先将它注释掉。

3.2 FileNotFoundException

🗳?FileNotFoundException文件找不到异常

🌱代码

package yuyi01;

import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;

public class ExceptionTest {

    @Test
    public void test10(){
        File file=new File("hello.txt");

        //FileNotFoundException 文件找不到异常
        FileInputStream fis=new FileInputStream(file);  //流直接操作文件

        //把文件内容直接读到内存中输出
        int data=fis.read();    //IOException 输入输出异常
        while(data!=-1){    //data为-1的时候退出,就是读完了
            System.out.print((char)data);
            data=fis.read();  //IOException 输入输出异常
        }

        //资源关闭
        fis.close();  //IOException 输入输出异常
    }
}

🍺异常

image.png

3.3 IOException

🗳?IOException输入输出异常

🌱代码

package yuyi01;

import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;

public class ExceptionTest {

    @Test
    public void test10(){
        File file=new File("hello.txt");

        //可能报FileNotFoundException 文件找不到异常
        FileInputStream fis=new FileInputStream(file);  //流直接操作文件

        //把文件内容直接读到内存中输出
        int data=fis.read();    //可能报IOException 输入输出异常
        while(data!=-1){    //data为-1的时候退出,就是读完了
            System.out.print((char)data);
            data=fis.read();  //可能报IOException 输入输出异常
        }

        //资源关闭
        fis.close();  //可能报IOException 输入输出异常
    }
}

🍺异常

读的时候可能不通畅:

image.png

结束的时候可能也不通畅:

image.png


?补充

FileNotFoundExceptionIOException都是可能出现的异常,怎么处理呢?

先写一个文件:(字符集改为UTF-8)

image.png

将路径改为:"D:\\hello.txt"

如下:

image.png

"D:\\hello.txt",一条右斜线会报错(一条表示转义的意思),需要写两条。或者写反斜杠 /。

现在文件就能找到了,但为啥还是报错?

所以需要提前预知一下处理的事情,大家感受一下,throws出去,将可能会报的异常给处理了,如下:

image.png

来运行一下:

image.png

这里出问题的原因是因为刚才文件里面写的是汉字,一个汉字可能会占多个字节,此时代码int data=fis.read();是一个字节一个字节地读,以后讲IO流的时候会专门解决这个问题。

那就先写成英文吧:

image.png

再次运行:

image.png

刚才我们将异常处理了,那程序在运行当中出现异常了吗?

其实是没出现异常。但是不处理的话,编译又不让过。(虽然程序没有问题,但是也需要处理一下,未雨绸缪)

🌱代码

package yuyi01;

import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ExceptionTest {

    @Test
    public void test10() throws FileNotFoundException, IOException {
        File file=new File("D:\\hello.txt");

        //可能报FileNotFoundException 文件找不到异常
        FileInputStream fis=new FileInputStream(file);  //流直接操作文件

        //把文件内容直接读到内存中输出
        int data=fis.read();    //可能报IOException 输入输出异常
        while(data!=-1){    //data为-1的时候退出,就是读完了
            System.out.print((char)data);
            data=fis.read();  //可能报IOException 输入输出异常
        }

        //资源关闭
        fis.close();  //可能报IOException 输入输出异常
    }
}

4、代码

仅供参考。

🌱代码

package yuyi01;

import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
import java.util.Scanner;

/**
 * ClassName: ExceptionTest
 * Package: yuyi01
 * Description:
 *
 * @Author 雨翼轻尘
 * @Create 2023/12/28 0028 10:28
 */
public class ExceptionTest {
    @Test
    public void test1(){
        //数组角标越界 ArrayIndexOutOfBoundsException
        int[] arr=new int[10];
        System.out.println(arr[10]);
    }

    @Test
    public void test2(){
        //空指针异常 NullPointerException
        String str="hello";
        str=null;   //指针指向为空
        System.out.println(str.toString());
    }

    @Test
    public void test3(){
        //空指针异常 NullPointerException
        int[] arr=new int[10];  //一维数组
        arr=null;
        System.out.println(arr[0]);
    }

    @Test
    public void test4(){
        //空指针异常 NullPointerException
        int[][] arr1=new int[10][]; //二维数组
        System.out.println(arr1[0][0]);
    }

    @Test
    public void test5(){
        //类转换异常 ClassCastException
        Object obj=new String();    //new一个String对象,将它赋值给Object类
        //String str=(String) obj;    //不会出现强转异常
        Date date=(Date) obj;   //转换为别的类型就不行了
    }

    @Test
    public void test6(){
        //NumberFormatException 数据格式化异常
        String str1="123";
        int i1 = Integer.parseInt(str1);  //可以将String类型的“123”转化为int类型的123

        String str2="abc";
        int i2 = Integer.parseInt(str2);    //不可以转换,会报错

        System.out.println(i1);
        System.out.println(i2);
    }

    @Test
    public void test7(){
        //InputMismatchException 输入类型不一致
        Scanner scanner=new Scanner(System.in);
        int num= scanner.nextInt(); //若输入的不是int类型,则会报错
        System.out.println(num);
    }

    @Test
    public void test8(){
        //ArithmeticException 算术异常
        int num=10;
        System.out.println(num/0);  //编译的时候不报错,运行的时候报错
    }

    //**********************以上是运行时异常,以下是编译时异常****************************

    @Test
    public void test9(){
        //ClassNotFoundException 类找不到异常
        //Class clz=Class.forName("java.lang.String");  //反射
    }

    @Test
    public void test10() throws FileNotFoundException, IOException {
        File file=new File("D:\\hello.txt");

        //可能报FileNotFoundException 文件找不到异常
        FileInputStream fis=new FileInputStream(file);  //流直接操作文件

        //把文件内容直接读到内存中输出
        int data=fis.read();    //可能报IOException 输入输出异常
        while(data!=-1){    //data为-1的时候退出,就是读完了
            System.out.print((char)data);
            data=fis.read();  //可能报IOException 输入输出异常
        }

        //资源关闭
        fis.close();  //可能报IOException 输入输出异常
    }
}

🍺输出结果

image.png
image.png

文章来源:https://blog.csdn.net/m0_55746113/article/details/135473445
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。