Java中的异常

知识点模块:
一.异常概述:

二.异常的处理方式
     1.JVM默认处理方式
     2.throw关键字抛出异常
     3.throws关键字异常声明
     4.编译时异常与运行时异常
     5.try...catch...finally
     6.异常在编译时的使用规则
     7.异常体系的方法
     8.自定义异常
详细代码在下面的gitee链接的Day21文件中
JavaSE: Java基础


一.异常概述:
    什么是异常?
       异常指的是java程序在运行期间出现的问题

    异常的设计思想:
        由于java是纯面向对象语言,因此Java将程序中可能出现的问题都映射成了Java类
         映射的Java类最终形成了异常体系
       异常体系:
          Thorwable
             Exception:java程序中出现的异常都是Excettion类或者Exception的子类
             Error:程序中出现的错误,例如:服务器宕机,内存溢出
                    我们一般改代码或者修改硬件来解决

二.异常的处理方式
    1.JVM默认处理方式
         参照图解

    2.throw关键字抛出异常
         手动处理异常
           我们可以通过throw关键字抛出一个异常对象
             格式:throw new 异常类的构造方法
             注意事项:
                 一旦执行throw new 异常类的构造方法;语句,该语句下面的代码都不在执行
                 throw new 异常类的构造方法下面不能有任何语句马,因为永远执行不到

/*
手动处理异常
  我们可以通过throw关键字抛出一个异常对象
    格式:throw new 异常类的构造方法
    注意事项:
        一旦执行throw new 异常类的构造方法;语句,该语句下面的代码都不在执行
        throw new 异常类的构造方法下面不能有任何语句马,因为永远执行不到
 */
public class ExceptionDemo02 {
    public static void main(String[] args) {
        int[] arr = new int[3];
    /*    int i = method(arr, 2);
        System.out.println(i); //0*/

        int i = method(null, 1);
        System.out.println(i);

        int j = method(arr, 5);
        System.out.println(j);

    }

    public static int method(int[] arr, int index) {
        //如果传null
        /*
        当arr==null的时候,return -1 会产生歧异
        1.定义method()方法的人认为如果arr为null,无法从数组中取元素,因此返回-1
        2.使用method()方法的人认为如果arr为null,结果返回 -1 认为数组中1索引位置元素值为 -1
        return 后面无论写任何值,都不能避免这个歧义
        throw 后面抛出的异常类,只能是异常体系的一员
         */
        if (arr == null) {
            //return -1;
            throw new NullPointerException("arr的值不能为null");
            //throw new String("abc");
        }
        if (!(index > 0 && index <= arr.length - 1)) {//索引错误的范围
            throw new ArrayIndexOutOfBoundsException(index + "这个索引超出数组索引范围");
            //int i=3;   //异常就停止执行代码,永远执行不到这句代码
        }
        return arr[index];
    }

}
    3.throws关键字异常声明
         throws关键字
            当方法中抛出异常对象,我们为了让调用者知晓这个方法可能又异常抛出
            需要在方法上通过throws关键字声明异常类
            格式:
               修饰符 返回值类型 方法名(形参列表) throws 异常类名1,异常类名2,....{

               }

import java.sql.SQLOutput;

/*
throws关键字
   当方法中抛出异常对象,我们为了让调用者知晓这个方法可能又异常抛出
   需要在方法上通过throws关键字声明异常类
   格式:
      修饰符 返回值类型 方法名(形参列表) throws 异常类名1,异常类名2,....{

      }
 */
public class ExceptionDemo03 {
    public static void main(String[] args) throws Exception{//main方法这里的throws异常声明是给jvm看的
                                                            //
       /* int totalPrice = getTotalPrice(3, 20);
        System.out.println(totalPrice);*/

     /*   int totalPrice2 = getTotalPrice(-2, 30);
        System.out.println(totalPrice2);//-60*/

        int totalPrice3 = getTotalPrice(2, -30);
        System.out.println(totalPrice3);

    }

    /**文档注释
     *
     * @param price  单价
     * @param amount  数量
     * @return    返回总价
     */
    public static int getTotalPrice(int price, int amount) throws Exception{//这个异常申明是给调用getPrice()方法的调用者看的
                                                                            //当他看到这个异常声明就知道需要处理
        if (price < 0) {
            throw new Exception("价格不能为负值"+price);
        }

        if (amount < 0) {
            throw new Exception("数量不能为负值" + amount);
        }
        return price * amount;
    }
}
    4.编译时异常与运行时异常
        异常类(Exception)类:
            运行时异常:RuntimeException类及 RuntimeException类的子类
            编译时异常:非RuntimeException类及 非RuntimeException类的子类
        运行时异常的特点:
            运行时异常可处理(throw,throws,try....catch)可不处理
            编译时异常如果代码中有异常(throw),那么需要处理(throws,try...catch)处理
        什么时候用运行时异常?
            如果程序中出现的问题无法再编译时期被检测,而需要在运行时期检测,那么我就需要使用运行时异常
            例如:例如数组索引越界,数组在运行时期才会在堆内存开辟数组,此时才回去找索引,当索引超出边界时候才报错
        什么时候用编译时异常?
            如果程序中出现的问题可以在编译时期检测,那么我们可以考虑使用编译时异常
            例如:价格和数量一旦有负值,我们知道计算总价肯定出问题

Father类
import java.io.IOException;
import java.util.zip.DataFormatException;

/*
编译时异常在注释中的使用规则:
   1.如果父类中的方法声明的有异常,那么子类在重写该方法的时候,
     可以不声明该异常或者声明该异常或者声明该异常的子类
   2.如果父类中的方法声明多个异常,那么子类在重写该方法的时候,
     可以声明父类异常的子集(包含空集)
      {a,b} {a} {b} {a,b} 空集
   3.如果没有声明异常,子类在重写该方法时也不能声明异常

 */
class Father {
    public void method01() throws Exception {

    }

    public void method02() throws Exception {

    }

    public void method03() throws Exception {

    }
    public void method04()throws DataFormatException,IOException {

    }
    public void method05()throws DataFormatException,IOException {

    }
    public void method06()throws DataFormatException,IOException {

    }
    public void method07(){

    }
}

class Son extends Father {
    @Override
    public void method01() {

    }

    @Override
    public void method02() throws Exception {

    }
    @Override
    public void method03() throws IOException {

    }
    @Override
    public void method04()throws DataFormatException,IOException {

    }
    @Override
    public void method05()throws DataFormatException {

    }
    @Override
    public void method06() {

    }

   /* @Override
    public void method07() throws Exception {

    }*/
}
Son类

import java.io.IOException;
import java.util.zip.DataFormatException;

/*
编译时异常在注释中的使用规则:
   1.如果父类中的方法声明的有异常,那么子类在重写该方法的时候,
     可以不声明该异常或者声明该异常或者声明该异常的子类
   2.如果父类中的方法声明多个异常,那么子类在重写该方法的时候,
     可以声明父类异常的子集(包含空集)
      {a,b} {a} {b} {a,b} 空集
   3.如果没有声明异常,子类在重写该方法时也不能声明异常

 */
class Father {
    public void method01() throws Exception {

    }

    public void method02() throws Exception {

    }

    public void method03() throws Exception {

    }
    public void method04()throws DataFormatException,IOException {

    }
    public void method05()throws DataFormatException,IOException {

    }
    public void method06()throws DataFormatException,IOException {

    }
    public void method07(){

    }
}

class Son extends Father {
    @Override
    public void method01() {

    }

    @Override
    public void method02() throws Exception {

    }
    @Override
    public void method03() throws IOException {

    }
    @Override
    public void method04()throws DataFormatException,IOException {

    }
    @Override
    public void method05()throws DataFormatException {

    }
    @Override
    public void method06() {

    }

   /* @Override
    public void method07() throws Exception {

    }*/
}
    5.try...catch...finally
        a.try...catch处理单个异常
           手动处理异常
             我们可以通过throw关键字抛出一个异常对象
               格式:throw new 异常类的构造方法
               注意事项:
                   一旦执行throw new 异常类的构造方法;语句,该语句下面的代码都不在执行
                   throw new 异常类的构造方法下面不能有任何语句马,因为永远执行不到
        b.try...catch处理多个异常
           手动处理异常
              格式:
                 try{//检测可能出啊先异常的代码
                    //一般写可能出现异常的代码

                 }catch(异常类型 变量名){//捕获异常对象
                                       //catch中异常类型定义为try中可能出现的异常类型
                   //处理异常的代码
                 }catch(异常类型2 变量名){  //不同的异常要找对应的catch处理,相当于对症下药

                 }....后面可以写多个catch块
        c.finally代码块
              第一种格式:
                 try{
                     //第一种可能:try中的代码没有抛出异常,那么会去执行finally中的语句,程序继续向下执行
                     //第二种可能:try中的代码出现了异常,异常下面的代码不再执行(try中的),接着会去找对应的catch处理这个异常
                                执行catch中的语句,执行完catch中的语句,接着会去执行finally中的语句
                                finally语句执行完之后,程序继续向下执行
                 }catch(异常类型 变量名){

                 }....finally{  //finall跟在最后一个catch末尾
                     //无论try中是否抛出异常,finally中的语句都会执行
                     //我们一般把资源释放语句放在finally中,防止资源无法释放,例如:IO流关闭,数据连接关闭...
                 }

              第二种格式:
                 try{
                     //第一种可能:try中的代码没有抛出异常,那么会去执行finally中的语句,程序继续向下执行
                     //第二种可能:try中的代码出现了异常,此时try下面的语句不再执行(try中),接着会去执行finally中的语句
                                执行完finally中的语句之后,JVM还去处理这个异常,采用默认处理方式,打印异常信息和异常追踪信息
                                最后停止程序
                 }finally{
                     //无论try中是否抛出异常,finally中的语句都会执行
                 }
        d.try...catch注意事项
              try...catch注意事项:
                 1.如果多个catch中的异常类型没有父子关系,那么多个catch的顺序不影响最终结果
                 2.如果多个catch中的异常又父子类型,那么父类型的catch不能放在子类型的上面
                   因为无论子类型异常对象,还是父类型异常对象都会被父类型的catch捕获,那么在父类型catch下面的子类型catch将永远执行不到
                  解决方案:
                     将子类型catch放在父类型的catch上方

/*
第一种格式:
   try{
       //第一种可能:try中的代码没有抛出异常,那么会去执行finally中的语句,程序继续向下执行
       //第二种可能:try中的代码出现了异常,异常下面的代码不再执行(try中的),接着会去找对应的catch处理这个异常
                  执行catch中的语句,执行完catch中的语句,接着会去执行finally中的语句
                  finally语句执行完之后,程序继续向下执行
   }catch(异常类型 变量名){

   }....finally{  //finall跟在最后一个catch末尾
       //无论try中是否抛出异常,finally中的语句都会执行
       //我们一般把资源释放语句放在finally中,防止资源无法释放,例如:IO流关闭,数据连接关闭...
   }

第二种格式:
   try{
       //第一种可能:try中的代码没有抛出异常,那么会去执行finally中的语句,程序继续向下执行
       //第二种可能:try中的代码出现了异常,此时try下面的语句不再执行(try中),接着会去执行finally中的语句
                  执行完finally中的语句之后,JVM还去处理这个异常,采用默认处理方式,打印异常信息和异常追踪信息
                  最后停止程序
   }finally{
       //无论try中是否抛出异常,finally中的语句都会执行
   }

 */
public class ExceptionDemo06 {
    public static void main(String[] args) throws Exception{//main方法这里的throws异常声明是给jvm看的

        //method01();
        try {
          /*  int totalPrice = getTotalPrice(3, 20);
            System.out.println(totalPrice);*/

            int totalPrice = getTotalPrice(-3, 20);
            System.out.println(totalPrice);

        }finally{
            System.out.println("fially中的代码语句被执行");
        }
        System.out.println("程序执行结束");


    }
    /**文档注释
     *
     * @param price  单价
     * @param amount  数量
     * @return    返回总价
     */
    public static int getTotalPrice(int price, int amount) throws Exception{
        //当他看到这个异常声明就知道需要处理
        if (price < 0) {
            throw new Exception("价格不能为负值"+price);
        }

        return price * amount;
    }

    private static void method01() {
        try {
           /* int totalPrice = getTotalPrice(3, 20);
            System.out.println(totalPrice);*/
            int totalPrice = getTotalPrice(-3, 20);
            System.out.println(totalPrice);

        } catch (Exception e) {
            System.out.println("捕获了Exception异常");
        }finally{
            System.out.println("fially中的代码语句被执行");
        }
        System.out.println("程序执行结束");
    }


}
    6.异常在编译时的使用规则
              编译时异常在注释中的使用规则:
                 1.如果父类中的方法声明的有异常,那么子类在重写该方法的时候,
                   可以不声明该异常或者声明该异常或者声明该异常的子类
                 2.如果父类中的方法声明多个异常,那么子类在重写该方法的时候,
                   可以声明父类异常的子集(包含空集)
                    {a,b} {a} {b} {a,b} 空集
                 3.如果没有声明异常,子类在重写该方法时也不能声明异常

    7.异常体系的方法
             Throwable中的方法:被所有的异常类继承,所有的异常对象都可以使用
                 String getMessage()
                       返回异常对象中封装的异常信息

                 void printStackTrace()
                       打印的时异常信息和异常追踪信息

    8.自定义异常
         将AgeException继承Exception类或者RuntimeException类就可以成为异常体系的一员
         如果继承Exception代表这个自定义异常为编译时异常
         如果继承RuntimeExceptio那么这个异常就是运行时异常
         class 类名 extends Exception 或RuntimeException{
               public 类名(){
                    super();
               }
               public 类名(String message){
                  super(message);

               }
         }

自定义异常

/*
将AgeException继承Exception类或者RuntimeException类就可以成为异常体系的一员
如果继承Exception代表这个自定义异常为编译时异常
如果继承RuntimeExceptio那么这个异常就是运行时异常
 */
public class AgeException extends Exception {
    public AgeException() {
    }

    public AgeException(String str) {
        super(str);
    }
}

Person类


public class Person {
    private int age;
    public Person(int age) throws AgeException{
        if (age < 0) {
       /*
    当年龄<0的时候,我们考虑抛出一个异常对象,提示调用者
    但是为了让这个异常对象见名知意,所以我们不抛出Exception
    throw new 年龄异常();
     */
            //throw new AgeException();
            throw new AgeException("年龄不能为" + age);
        }
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age)throws AgeException {
        if (age < 0) {

            throw new AgeException();
        }
        this.age = age;
    }
}

测试模块

public class Demo01 {
    public static void main(String[] args) throws AgeException{
        Person p = new Person(-10);
        p.setAge(12);
        System.out.println(p.getAge());

    }
}

运行结果

  • 14
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值