【Java】异常处理详解

目录

引言:

异常的概述与异常的分类:

Error:

 Exception:

RuntimeException

非RuntimeException

常见的异常

异常的处理方式

方式一:try-catch-finally

finally的使用

 catch语句的顺序

 方式二:throws方法

 重写方法异常抛出的原则

手动抛出异常

自定义异常类


引言:

异常,可能是我们写程序的过程中最不希望出现的东西了,谁不希望自己的程序尽善尽美呢,但程序你写出来是要为别人使用来创造价值的,在这个过程中,难免可能会出现一些不尽如人意的情况,接下来我们就来说说。

异常的概述与异常的分类:

java中对异常也进行了分类处理,那么它都有哪些分类呢?

我们打开API看一下

异常类(Throwable),有两个直接的子类,分别是:Error,Exception ;并且它们都实现了一个接口Serializable 

接下来,我们分别来看一下这两个子类:

Error:

 

 

从API里的描述,我们可以看出,Error一般是比较严重的问题(比如:java内部系统错误,资源耗尽,StackoverflowError等),所以我们一般不对Error进行异常处理,通常要对我们的代码逻辑进行思考改进。

 Exception:

 Exception的子类可是非常多了,当然,我们没必要去死记硬背这些东西;Exception异常内部又分为了两类,图中我绿色箭头指向的地方:RuntimeException (运行时异常)。

RuntimeException

 

点进来之后,我们可以看到RuntimeException ,内部还有很多的子类。

非RuntimeException

那么除了运行时异常,剩下的都是编译时异常了,也可以说是编译时异常。

常见的异常

异常类内部都有哪些常见的异常呢?

我们平常写代码中也会出现错误,你比如说数组访问越界,空指针等等

数组访问越界:

空指针异常:

 

 

 此外还有NullPointerException,ArithmeticException,NumberFormatException..等等,都可以在API上找到,并查看其详细的内容。

对于这些错误,既可以在运行时候中止掉它们,也可以在我们编程的时候提前考虑到可能出现的错误,并对它们进行处理。

异常的处理方式

方式一:try-catch-finally

使用格式:

  try{
         //可能出现异常的代码
  }catch(异常类型1 变量名1){
         //处理异常的方式1
  }catch(异常类型2 变量名2){
         //处理异常的方式2
  }catch(异常类型3 变量名3){
        //处理异常的方式3
  }

  ....

  finally{

        //一定会执行的代码
  }

我们直接来段代码感受一下:

 

 这段代码中,我们在进行a,b两个变量相除的过程中,由于可能会出现分母为0的情况,所以我们用try-catch-finally语句块对它进行处理。

printStackTrace使用来打印错误信息的,我们可以打开它的源码看一下。

finally的使用

那么我们再来看一下,为什么会打印"-----qiqi------"这句话呢?

很显然,这和finally这个语句块儿有关了,它里面的语句是一定会被执行的 

 

但是finally在我们这个程序里,好像是可有可无的,那我们看去了可不可以呢 

 

很明显,没有问题,那finally语句存在的条件是什么呢? 

其实,finally在一些情境下编程时是十分必要的,比如当你打开一个文件想对它操作是,或者你想运行一个数据库的时候,这时候,你用完,无论是成功或是出现异常,我们都希望能关闭掉它,finally里面经常写这样子的语句。

我们再来看一段代码:这是一个类型转换的例子

 

 运行过后我们发现

其实异常之后要报出来的信息,我们是可以自己写成比较人性化的语句的,防止用户使用的时候看到一堆乱码,降低其体验感。 

 catch语句的顺序

 我们把上面的代码中几个catch语句的顺序调整一下,看会出现什么情况。

 

 

 

 

只有当我们把Exception放到 任意其他两个前面,程序都会报错,这是为什么呢?

首先我们可以发现的是,NullPointerException和NumberFormatException都是Exception的子类,

到这里我们可以思考一下;

Exception的范围肯定比子类的大,当他写在前面的时候,是不是其他的两个子类压根没机会执行了;所以当异常类有子父类关系的时候,我们一定要注意catch语句的顺序。

 

 方式二:throws方法

在编写程序的时候,我们可能并不能确定怎么处理这种异常,此时我们可以用throws将该方法的异常抛出给调用者来进行处理。

 

 这上面这段代码中,我们在divide方法中考虑到分母不能为0的情况,排除了异常Exception,此时你在调用的时候如果不对方法进行处理,我们可以看到,编译的时候就会报错!

我们在处理的时候,仍然要用到try-catch语句块儿来进行处理。

public class ThrowsTest {


    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int result = 0;
        try {
            result = div(4,2);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(result);
    }

    public static int div(int x,int y) throws Exception {
        int result = x / y;
        return result;
    }
}

处理之后,如果你在为分母赋值为0的情况下,我们的try-catch就会对异常进行处理。

 

由此我们可以看出,throws并没有真正的处理掉异常,而只是将异常抛给了他的调用者去处理。

 重写方法异常抛出的原则

 

 

 

我们知道,NumberFormatException和NullPointerException是Exception的子类;

原则:当我们写一个异常类的子类去继承父类的时候,子类抛出的异常的范围要是 大于父类抛出的异常范围则会报错!

手动抛出异常

以上的这些异常都是系统在编译和运行时自动识别帮我们抛出的,除了这种由系统自动进行的情况呢,也可根据人工需求手动进行抛出

我们以一个简单的例子来说明这一点:

public class StudentTest {
    public static void main(String[] args) {
        Student s = new Student();
//        s.setId(123);
        try {
            s.setId(-123);
            System.out.println(s.toString());
        }catch(Exception e){
            e.printStackTrace();
        }
    }

}


class Student{

    private int id;

    public void setId(int id) throws Exception {
        if(id > 0){
            this.id = id;
        }else{
            throw new Exception("输入的数据异常!");
        }
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                '}';
    }
}

这段代码中,当我们要设置的学号为负数时,我们需要提醒输入者,输入的数据是有异常的。

 这里我们在方法内部将异常类创建出来所使用的关键字是:throw,这里要注意区分throws和throw的区别。

throw是方法内部将异常对象创建出来的;

throws是方法声明时,将异常抛出给调用者的;

如果我们设置的是负数的话,则会对异常进行处理(这里的错误信息是我们调用printStackTrace产生的)。

 

自定义异常类

了解了异常类之后,那我们如何自定义一个异常类来使用呢?

不会没关系,我们可以打开jdk源码,看看它是怎么定义的,我们照猫画虎。

上来就定义了一大串数字;其实这里是一个序列号,不了解没关系,我们照这样子来就可以;

剩下的还有一些重载的构造器,有无参的,还有一个参数是messasge的 ,下面还有一些其他参数的构造器,我们可以自己打开看看。

 异常类是有体系的,就算是我们自定义也要和人家的体系相符,也就是说我们自定义的异常类要继承于现有的异常类,一般情况下我们都不去继承Error类。

自定义异常类:

public class MyException extends Exception{
    static final long serialVersionUID = -3387516993124229989L;
    private int age;

    public MyException(){
        super();
    }

    public MyException(String message ){
        super(message);
    }

    public int getAge(){
        return age;
    }
}

 

自定义异常类的测试:

public class MyExceptionTest {

    public void myAge(int age) throws MyException{ //写他的父类Exception也可以
        if(age >= 0 && age < 200){
            System.out.println("您的年龄为:" +age);
        }else{
            throw new MyException("你输入的年龄非法,请重新输入");
        }
    }

    public static void main(String[] args) {
        MyExceptionTest m = new MyExceptionTest();
        try {
            m.myAge(200);
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}

运行结果: 

 

总的来说,异常这块还是不难的,大家加油努力学习! 

 

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 异常处理是为了让程序更加健壮,当程序遇到错误或异常情况时,能够正确处理异常并给出有意义的反馈,而不是直接崩溃。异常处理的基本语法包括使用 try-catch-finally 块来捕获和处理异常。在编写 Java 代码时,需要注意处理 Checked 异常,避免将 Unchecked 异常泄露到用户界面。此外,还可以使用 assert 关键字、异常链、异常屏蔽和自定义的异常处理器等异常处理技巧来提高程序的健壮性和稳定性。在实际开发中,也可以借助一些优秀的开源 Java 异常处理库来简化异常处理的工作,例如 log4j、Apache Commons Lang、Guava 和 Sentry 等。\[1\]\[3\] #### 引用[.reference_title] - *1* *3* [Java 异常处理详解](https://blog.csdn.net/u012581020/article/details/130657212)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [2020-11-08](https://blog.csdn.net/weixin_39743450/article/details/109558433)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值