Java异常处理篇

在这里插入图片描述

1、什么是异常处理?

在了解什么是异常处理之前,我们不妨先了解一下什么叫异常。所谓异常就是非正常的,例外的。每一个软件程序在被编写初期都会产生异常,任何语言都一样,都会产生错误,Java也不例外。
像我们平时常见的:1、除数为零2、数组越界,都属于异常。
当我们编写的程序可能会发生异常时,就需要我们把异常捕获和异常处理。这个过程就叫做异常处理。

2、Java中都有哪些错误?

一般来说错误分为编译错误处理错误

(1)、编译错误

编译错误是指我们在日常编写代码时,可能对Java语言的语法不太了解,如 Java的语法要求在每一条语句结尾以;结束。或者对保留字的拼写不正确,或者大小写没有区分开,英文;写成中文 ,等都会造成编译错误。

(2)、运行错误

运行错误通俗的讲就是,程序在语法上是正确的,程序能够编译并运行,但是运行的结果与预想的不同,这种情况可能是程序员的算法考虑不周造成的。比如死循环就是一个典型的运行错误,在编写程序时尽量避免出现死循环,以免出现系统崩溃等不必要的麻烦。

3、异常和错误的继承结构图

在Java中所有的异常和错误都继承于Throwable类,继承的结构图如下:
在这里插入图片描述
Throwable有两个子类分别是ErrorException

(1)、Error类

Error类继承于Throwable类,一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出等。对于这类错误,一般由JVM抛出。这种错误仅靠程序本身无法恢复和预防,遇到这样的错误时,应尽力使程序安全退出。
Error类包含很多子类:

异常异常对应的错误
VirtualMachineError虚拟机错误
IOError输入输出错误
AssertionError断言错误

(2)、Exception类

Exception类也继承于Throwable类,指Java程序应该捕获的异常。其中,java.lang.RuntimeException是其中一个特别的子类。RuntimeException类表示编程时存在的隐患或者在运行时由JVM产生的异常,如除数为零,数组越界,空指针等等。

Exception类也包含很多子类:

异常异常对应的错误
RuntimeException运行时异常
NullPointException空指针异常
IOException输入输出异常
SQLExceptionSQL异常
ClassNotFoundException未找到类异常
TimeoutException超时异常

4、用户自定义异常

有时候系统定义的异常并不能满足我们的需求,而且系统定义的异常大多数是英文,看起来很费劲。此时我们可以自己定义异常,用它来满足我们的逻辑要。

使用自定义异常一般有如下步骤:
	(1)继承java.lang.Exception类或者
			其他已存在的系统异常类,或者
			用户自定义类来声明自定义的异
			常类。
	(2)在自定义的方法中声明该异常
			 类所需的成员属性和成员方法,
			 使它满足我们的逻辑需求。

例如:当用户年龄小于0岁时就报年龄不可小于零的错误


class  ExceptionOne extends Exception{//声明一个异常类,继承于Exception
  public ExceptionOne(String ErrorMsg){
       super(ErrorMsg);
   }
}
class  Person{
    private int age;
    Person(int age){
        this.age=age;
    }
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
public class Main {
    public static void main(String[] args) {
        Person p1 =new Person(-10);
        if (p1.getAge()<0){
            try {
                throw (new ExceptionOne("年龄不可小于零"));
            } catch (ExceptionOne exceptionOne) {
                exceptionOne.printStackTrace();
            }
        }
    }
}
ExceptionOne: 年龄不可小于零
at Main.main(Main.java:27)

5、如何抛出并捕获异常?

可以使用throwthrows来抛出异常,使用try...catch来捕获异常。

(1)抛出单个异常

在上面的例子中,我们使用throw抛出了ExceptionOne异常,这是手动抛出异常的方法。对于系统定义的异常会由JVM自动抛出。

例如,当我们不小心把0作为除数的话,IDEA并不会报错,当运行时才会报java.lang.ArithmeticException: / by zero的错误。

public class Main {
    public static void main(String[] args) {
        int x=6,y=0;
        System.out.println(x/y);
    }
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:5)

当一个函数使用throw抛出了异常,并且在函数中并没有去处理此异常时,此时需要在函数头用throws子句来向调用此函数者抛出异常。若上层的函数也没有处理这个异常,则继续向上抛,直到找到能处理该异常方法。

下面这段程序是错误的。
解决方法在程序段下面,可以尝试先不看,然后自己寻找解决方法。

class  ExceptionOne extends Exception{
  public ExceptionOne(String ErrorMsg){
       super(ErrorMsg);
   }
}
class Person{
    private int age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Person(int age) {
        this.age = age;
    }
}
public class Main {
    public static void main(String[] args){
        func1();
    }

    public static void func1() throws ExceptionOne {
        func2();
    }

    public static void func2() throws ExceptionOne{
        Person p1=new Person(-10);
        if (p1.getAge()<0){
            throw new ExceptionOne("年龄不可小于零");
        }
    }
}

解决方法:
(1)、在main主方法后添加throws ExceptionOne,throw后面的异常类可以是此异常类的父类或者间接父类。因为ExceptionOne类继承了Exception类,所以也可以在main主方法后添加throws Exception来处理异常。
(2)、将main主方法里的func1()用try…catch语句包裹起来就像下面这样

public static void main(String[] args){
        try {
            func1();
        } catch (ExceptionOne exceptionOne) {
            exceptionOne.printStackTrace();
        }
    }

(2)抛出多个异常

在这里插入图片描述
一个函数中出现多种异常时,可以用try…catch来捕获异常。例如在一个方法中出现了Exception_one、Exception_two、Exception_three三种异常,并且这三种异常都继承了Exception_super类。我们可以使用多个catch来分别捕获Exception_one、Exception_two、Exception_three三个异常。

class Exception_one extends Exception{//第一个异常类
    Exception_one(String ErrorMsg){
        super(ErrorMsg);
    }
}class Exception_two extends Exception{//第二个异常类
    Exception_two(String ErrorMsg){
        super(ErrorMsg);
    }
}class Exception_three extends Exception{//第三个异常类
    Exception_three(String ErrorMsg){
        super(ErrorMsg);
    }
}
public class Main {
    public static void main(String[] args) {
		func();
    }
    public static void func(){
        try{
            //这里可能会出现Exception_one、Exception_two、Exception_three三种错误
        }catch (Exception_one e1){
            e1.printStackTrace();
        }catch (Exception_two e2){
            e2.printStackTrace();
        }catch (Exception_three e3){
            e3.printStackTrace();
        }
    }
}

同样地,类似throwthrows,catch也可以捕获该异常类的子类,将上面func()函数写成这样也是可以的

   public static void func(){
        try{
            //这里可能会出现Exception_one、Exception_two、Exception_three三种错误
        }catch (Exception e1){
            e1.printStackTrace();
        }
    }

当func()方法中出现了我们不清楚的异常时,我们可以用Exception来捕获,而不必表明异常的类型,系统会自动识别异常。

public class Main {
    public static void main(String[] args) {
    func();
    }
    public static void func(){
        try{
           int x=7/0;
        }catch (Exception e1){
            e1.printStackTrace();
        }
    }
}

为我们自动识别了,除数不可为0的异常。
java.lang.ArithmeticException: / by zero
at Main.func(Main.java:8)
at Main.main(Main.java:4)

(3)throw和throws的区别

throw:throw子句一般用在方法内部的try...catch还有try...catch...finally(一会讲)中,用于抛出异常。
throws:throws通常写在方法的签名处,也就是方法名的后面,用于向调用它的方法抛出异常。

(4)try…catch…finally的使用

finally的用法在我这篇《应届生必会!(超级进阶篇)Java面试中最常被问的知识》文章有所提及。
finally后的语句块无论如何都会被执行
看看代码,就懂了


public class Main {
    public static void main(String[] args) {
        System.out.println(func());
    }
   public static int func(){
       try{
        throw new Exception();
       }catch (Exception e){
           e.printStackTrace();
           return 2;
       }finally {
           System.out.println("finally被执行了");
           return 3;
       }
   }
}

结果为

 java.lang.Exception	
	at Main.func(Main.java:8)
	at Main.main(Main.java:4)
 finally被执行了
 3

在这里插入图片描述

创作不易,欢迎三连呀

评论 46
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java精灵儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值