java中的Exception--异常详解

异常

Java异常概念

​ 在使用计算机语言开发时,尽管代码没有问题,但在系统的运行过程中仍会遇到问题。简单来说就是代码运行时,由于各种原因导致程序不能正常的执行。

异常分类

​ 定义:Java语言中,将程序执行中发生的不正常的情况称为“异常”(这里我们认为开发过程中的语法错误和逻辑错误不是异常)。

​ 分类:Java程序在执行过程中所发生的异常(广义上的一切不正常)事件可分为两类—Error和Exception

​ Error:Java虚拟机无法解决的严重问题,一般不编写针对性代码进行处理。会出现Error的情况一般是内存空间不够,JVM系统内部错误,资源耗尽等等严重问题。(本文我们不讨论Error的问题)

​ Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性代码进行处理,即使用java的异常处理机制,控制后面的代码继续执行。(本文我们只讨论在编译程序时出现最多的Exception问题)

解决异常的两种方法

​ 1.遇到异常就终止程序的运行。

​ 2.编写程序时,就要考虑到异常的检测、异常消息的提示、以及异常的处理。

​ 如何捕获异常?答:捕获异常最理想的阶段就是在编译期间,但是仍有部分异常是出现在运行期间的。这样就会使异常出现两种不同的情况,编译时异常运行时异常

异常的体系

异常体系图

Throwable类:这是Java语言中所有错误和异常的顶级(超)类,它就是一个祖宗级别的大佬类。错误就是Error,可能会是系统错误,程序往往是不处理的。异常就是Exception,这是所有异常类的父类,也是编程人员最最关心的。

Exception类:就是异常,上面我们也说到了Exception类有两种:一种是运行期异常另一种就是编译期异常

运行期异常:程序运行时抛出的异常,所有RuntimeExcepetion的子类都是运行期异常。如:

ArithmeticException	数学算数异常
NullPointerException	空指针异常
ArrayIndexOutOfBoundsException	数组索引越界异常
......

编译期异常:除去运行期的异常都是编译期异常,一般也称检测异常,会在编译的时候就提示有误,需要你在代码编译期间对其作出修改。

IQException
SQLException
ParseException
......

在这里插入图片描述

代码示例

//示例1	
//ArrayIndexOutOfBoundsException 抛出以表示使用非法索引访问数组。 索引为负数或大于或等于数组的大小。
int [] a = new int[5];
     a[5] = 10;
System.out.println(a[5]);
//上面的代码运行后出现如下异常
/*
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 (5表示非法索引值)
   at yichang.ExceptionDemo1.main(ExceptionDemo1.java:7)(//7表示在第七行出现错误)
*/

//示例2
//NullPointerException   空指针异常 用程序尝试在需要对象的情况下使用null时抛出 
String a = null;
a.length();//实质是null.length*/

异常处理

异常处理的流程

​ JVM默认的异常处理方式是当控制台抛出对应类型的异常对象(异常信息)时终止程序,而Java编程语言使用异常处理机制为程序提供错误处理的能力。

​ 1.程序中预先设置好对付异常的处理办法

​ 2.程序开始运行

​ 3.出现异常

​ 4.对异常进行处理

​ 5.处理完毕,继续执行下面的代码

异常处理的实现

​ Java中的异常处理都是通过五个关键字来实现的:try、catch、finally、throw、throws。

关键字 作用
try 捕获异常,执行可能产生的异常代码。
catch 捕获异常。
finally 无论是否发生异常,finally内的代码都会执行。
throw 声明异常,声明方法中可能抛出的各种异常。
thros 手动抛出异常。

try、catch、finally一般是互相配合使用,他们的基本语法是:

try{
	//可能出现异常的代码,代码量尽量缩小
}catch(上面异常代码的异常类型){//当try出现异常时,执行catch
	//处理异常的方式
}finally{
	//必须执行的代码
}

代码示例

public class ExceptionDemo5 {
    
    
    //try{}catch(){}finally
    public static void main(String[] args) {
    
    
        //语法格式
        /*
        * try{
        *   //可能出现的异常代码,代码量范围尽量缩小
        * }catch(异常类型){
        *   //出现异常时的处理方式
        * }finally{
        *   //必须执行的代码
        * }
        */

        int a = 10;
        int b = 2;
        try{
    
    
            System.out.println(a/b);
        }catch(Exception e){
    
    
            System.out.println("错误");
        }finally{
    
    
            System.out.println("必须执行");//输出
        }
        int c = 0;
        try{
    
    
            System.out.println(a/c);
        }catch(Exception e){
    
    
            System.out.println("错误");
        }finally{
    
    
            System.out.println("必须执行");//输出
        }
    }
}
try

​ 检测可能会发现异常的代码块,try块中任何一条语句发生异常,下面的代码将不会被执行,程序将跳转到异常处理代码块中,即catch块。因此,不要随意将不相关的代码放入到try块中,因为随时可能会中断执行。

catch

​ 把抓到的类型匹配的异常捕获,保证程序能够继续运行下去,catch语句必须紧跟着try语句之后,称为捕获异常,也就是异常处理函数,一个try后面可以写多个catch,分别捕获不同类型的异常,要从子类往父类的顺序写,否则有编译错误。

finally

​ finally里面的语句块总会执行,一段代码只能有一个finally语句。

捕获异常信息

​ 与其它对象一样,都可以访问一个异常对象的成员变量或调用它的方法。

getMessage()

​ 获取异常信息,返回一个字符串。就像下面这个示例中的Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 5 这里的5就是getMessage()可以得到的字符串.

//示例1	
//ArrayIndexOutOfBoundsException 抛出以表示使用非法索引访问数组。 索引为负数或大于或等于数组的大小。
int [] a = new int[5];
     a[5] = 10;
System.out.println(a[5]);
//上面的代码运行后出现如下异常
/*
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 (5表示非法索引值)
   at yichang.ExceptionDemo1.main(ExceptionDemo1.java:7)(//7表示在第七行出现错误)
*/
printStackTrace()

​ 获取异常类名和异常信息, 以及异常出现出现在程序中的位置, 无返回值。如上面示例中的:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
   at yichang.ExceptionDemo1.main(ExceptionDemo1.java:7)

代码示例

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class GetExceptionDataDemo {
    
    
    public static void main(String[] args) {
    
    
        String str = "2020-11-10";
        SimpleDateFormat stf = new SimpleDateFormat("yyyy.MM-dd");
        try {
    
    
            Date date = stf.parse(str);
        } catch (ParseException e) {
    
    
            System.out.println(e.getMessage());//Unparseable date: "2020-11-10"
            e.printStackTrace();
            /*
            * java.text.ParseException: Unparseable date: "2020-11-10"
			at java.text.DateFormat.parse(DateFormat.java:366)
			at yichang.GetExceptionDataDemo.main(GetExceptionDataDemo.java:12)
			*/
        }
    }
}

throws 和 throw

throws

​ 1. throws,定义一个方法的时候可以使用throws关键字声明,表示此方法不处理异常,而交给方法调用处进行处理。

语法格式:
public void test throws 异常1,异常2,异常3....{

}

​ 2.任何方法都可以使用throws关键字声明异常类型,包括抽象方法

​ 3.子类重写父类中的方法,子类方法不能声明抛出比父类类型更大的异常

​ 4.使用了throws的方法,主要指编译期异常,调用时必须处理声明的异常,要么使用try-catch,要不继续使用throws声明。

代码示例—父

public abstract class ThrowsDemo {
    
    
    public abstract void chufa(int a, int b) throws Exception;
}

代码示例–子

import java.text.ParseException;

public class ThrowstestDemo extends ThrowsDemo{
    
    
    @Override
    public void chufa(int a, int b) throws ParseException {
    
    
        System.out.println(a/b);
    }
    public static void main(String[] args) throws ParseException {
    
    
        new ThrowstestDemo().chufa(2,2);//调用方法时必须要对异常方法进行处理 继续throws or try-catch
    }
}

throw

​ 1.throw关键字用于显式的抛出异常,抛出的是一个异常类的实例化对象。

​ 2.在异常处理中,try语句要捕获的是一个异常对象,那么此对象也可以自己抛出。

​ 3.在程序中主动抛出异常对象,在构造方法中可以填入错误信息。

代码示例

public class ThrowDemo {
    
    
    public static void main(String[] args) {
    
    
        int a =10;
        int b =0;
        try{
    
    
            System.out.println(a/b);
        }catch (ArithmeticException n){
    
    
            throw new ArithmeticException("分子不能为0");//在程序中主动抛出异常对象,在构造方法填入错误信息。
        }
    }
}

throws和throw的总结

​ 1.throw用于方法体中, 用来抛出一个实际的对象, 使用throw后, 要么使用try-catch捕获异常,要么使用throws声明异常

​ 2.throws用于方法声明处, 用来声明该方法可能发生的异常类型, 可以是多个异常类型, 用来强制调用该方法时处理这些异常.

​ 3.抽象方法也可以使用throws.

自定义异常

​ 1.自己定义的异常类, 也就是API中标准异常类的直接或间接子类

​ 2.作用: 用自定义异常标记业务逻辑的异常,避免与标准异常类混淆

​ 3.自定义异常类的语法:

public class 异常类名 extends Exception/RuntimeException{
	public 异常类名(String msg){
		super(msg);
	}
}

​ 4.自定义异常类通常不写其他方法,只重载需要使用的构造方法

​ 5.继承Exception, 在方法中使用throw抛出后, 必须在方法中try-catch或者throws抛出

代码示例

//自定义异常
//继承了一个Exception,使得自定义的类成为了一个异常类
public class fenshuExceptionDemo9 extends Exception{
    
    
//    定义了自身异常类的一个构造方法
    public fenshuExceptionDemo9(){
    
    
//    super() 调用了继承的Exception的一个传参的构造方法
        super("分数不合法");
    }

    public fenshuExceptionDemo9(int a){
    
    
        super("分数不合法");
    }
}

猜你喜欢

转载自blog.csdn.net/Lotus_dong/article/details/109759797