【学习笔记】JAVA基础——异常处理部分

前言

摸鱼了几天,重新开始学习= =。

这次是摸回JAVA基础的异常控制。之前一直都是直接用的IDEA的自动补全异常语句,但是隐约觉得这玩意还是得好好学习,所以今天抽空补补课。

学习网站是how2j,顺便复习复习IDEA上传到GIT的操作。(‾◡◝)

代码上传到git上了

简介

异常的定义:导致程序的正常流程被终端的事件。

为啥要整这玩意:进行某个程序操作时,可能是一个潜在的错误操作,如果不预先做好异常处理,那么就会导致编译错误。

一. try、catch与finally

① try && catch

  • 一个try对应一或多个catch。
  • try的代码块中只要遇到一个异常,就会直接中断。
  • 一组try && catch语句一般情况下只能抛出一个异常:因为遇到一个异常时,try代码块的运行就会直接中断,后面的触发异常语句不会被运行。不过可以通过其他方法来抛出多个异常,此处不展开说明。
  • Exception类是所有异常类的父类。
    因此,可以直接catch(Exception e),但是只限于只有一种异常的情况。
  • 多异常代码块的处理:多个catch、一个catch

以上内容及更多内容可见以下两份代码块内容

public class one {
    public static void main(String[] args)
    {
        // 此处不会报错,因为此时f只是一个定义了文件路径的File类,并没有真正访问这个路径
        File f = new File("/Users/fwy/Downloads/jojo.jpg");
        try
        {
            System.out.println("试图打开不存在的文件jojo.jpg");
            new FileInputStream(f);
            System.out.println("成功打开");
            // }catch (FileNotFoundException e){ // FileNotFoundException:文件不存在 异常
        }catch (Exception e){ // Exception:所有异常的父类,可以直接用于捕捉异常。
            System.out.println("jojo.jpg不存在噢!");
            // printStackTrace():这玩意是用来打印方法的调用痕迹的
            // 控制台的橙色部分就是该函数的打印内容
            // 在此例子中打印出了异常起始位置为第15行
            e.printStackTrace();
            // 打印 堆栈 痕迹
        }
    }
}
// 多异常捕捉
public class two {
    public static void main(String[] args)
    {
        // 方法一:分别对不同异常进行catch
        File f = new File("/Users/fwy/Downloads/QAQ.jpg");
        try
        {
            System.out.println("试图打开不存在的文件QAQ.jpg");
            new FileInputStream(f);
            System.out.println("成功打开!");

            int[] arr = new int[10];
            System.out.println(arr[10]);
            // 实际上只能捕捉到一个异常,捕捉到异常后就会直接中断
            // 比如本例中运行到18行就会直接中断,数组越界部分不会涉及到
        } catch (FileNotFoundException e)
        {
            System.out.println("文件不存在");
            e.printStackTrace();
        } catch (IndexOutOfBoundsException e)
        {
            System.out.println("数组访问越界");
            e.printStackTrace();
        }

        // 方法二:直接放在同一个catch里
        f = new File("/Users/fwy/Downloads/QVQ.jpg");
        try
        {
            System.out.println("试图打开存在的文件QVQ.jpg");
            new FileInputStream(f);
            System.out.println("成功打开!");

            int[] arr = new int[10];
            System.out.println(arr[10]);
        } catch (FileNotFoundException | IndexOutOfBoundsException e)
        {
            // 格式为 Exception1 | Exception2 e, IDE可以报出具体错误
            // 使用 instanceof 来区分异常,用于进行不同异常的处理
            if (e instanceof FileNotFoundException)
                System.out.println("文件不存在");
            else if (e instanceof IndexOutOfBoundsException)
                System.out.println("数组访问越界");
            e.printStackTrace();
        }
    }
}

② finally

  • 可以不写
  • 无论如何最后都会被执行

③ throws

  • throw与throws区别:
    throws:用于方法声明,代表异常出现的可能性,不一定会发生。
    throw: 出现于方法体内,实际上地抛出了异常对象
  • throws的使用情况:
    方法一调用方法二,方法二有异常但是选择不处理,而是抛出给方法一,让方法一处理。
    理解起来可能比较绕,可以参考以下代码:
    这里是主函数调用方法一,方法一调用方法二的嵌套关系。
    方法二出现异常后,由于方法二老渣男了,不想处理这个麻烦玩意,所以直接抛出给方法一。
    方法一也不想当老实人,但是无奈打不过主函数,所以不能抛出给主函数,只能自己默默处理。
public class three {
   // 同样不处理异常
   public static void main(String[] args)
   {
       method1();
       /*
       try
       {
           method1();
       } catch (FileNotFoundException e)
       {
           e.printStackTrace();
       }
       */
   }

   // 选择在method1中处理异常
   private static void method1() //throws FileNotFoundException
   {
       //method2();
       try
       {
           method2();
       } catch (FileNotFoundException e)
       {
           e.printStackTrace();
       }
   }

   // 不处理异常,而是抛出异常
   private static void method2() throws FileNotFoundException
   {
       File f = new File("/Users/fwy/Downloads/QAQ.jpg");
       System.out.println("试图打开不存在的文件QAQ.jpg");
       new FileInputStream(f);
       System.out.println("成功打开");
   }
}

不过其实我们也可以选择方法一继续抛出给主函数,最终只要有一个地方进行try-catch的异常处理即可。

补充:JVM 相关

  • 抛出异常语句(throw)都是通过 athrow 指令来实现(指令码)。抛指令
  • 异常捕获语句(catch)早期也是指令,但现在是通过异常表实现。抓打表

二. 异常的分类

① 分类解释与思维导图

  • Exception是所有异常的父类,Throwable是Exception和Error的父类
  • Exception 异常:是程序本身可以处理的异常
  • Error 错误:是程序无法处理的错误,大多为JVM出现的问题
  • Throwable可以被throws抛出,但是catch的也要是Throwable类
// 异常分类:1. 可查异常
//         2. 非可查异常:a.运行时异常  b.错误
public class one {
   public static void main(String[] args)
   {
       // 1. 可查异常 CheckedException:必须处理的异常,catch | throws,否则编译错误
       //    比如FileNotFoundException
       File f = new File("/Users/fwy/Downloads/QAQ.jpg");
       try
       {
           new FileInputStream(f);
           System.out.println("打开成功");
       }catch (FileNotFoundException e){
           e.printStackTrace();
       }

       // 2. 运行时异常 RuntimeException:不是必须处理的异常,不用catch | throws也可以编译
       //    比如NullPointException,ArrayIndexOutOfBoundsException等
       //    设计原因:Java中此类错误太过普遍,都进行捕捉的话,代码可读性不好
       int k = 5/0;

       String s = null;
       s.length();

       // 3. 错误 Error:系统级别的异常,通常是内存溢出。同2一样不要求强制捕捉
       StringBuffer sb = new StringBuffer();
       for (int i = 0; i < Integer.MAX_VALUE; i++)
       {
           // 不断增加字符导致内存用光,OutOfMemoryError
           sb.append('a');
       }
   }
}

思维导图
图源how2j

图片截自how2j

三. 自定义异常

定义:自定义一个异常类,继承Exception。
用途:用于自定义类中需要的异常,比如定义银行卡类,取款时可以抛出余额不足异常。

  • 有参构造与无参构造:见代码,主要是Exception的getMessage()的使用。
class Hero{
    String name;
    float hp;
    Hero(String name,float hp){this.name = name;this.hp=hp;}

    public void attack(Hero h) throws HeroIsDeadException
    {
        if(h.hp == 0)
            throw new HeroIsDeadException(h.name + "已经死了,别鞭尸了"); //使用throw而非throws抛出异常
    }

    class HeroIsDeadException extends Exception{
        public HeroIsDeadException() { } // 默认构造,信息更少,但是更方便

        public HeroIsDeadException(String msg) // 有参构造,导入异常原因,分析异常更方便
        {
            super(msg); // 可以使用getMessage()函数来获取具体异常信息
        }
    }
}

public class one {
    public static void main(String[] args)
    {
        Hero garen = new Hero("盖伦",600);
        Hero teemo = new Hero("提莫",0);
        try{
            garen.attack(teemo);
        }catch (Hero.HeroIsDeadException e){
            System.out.println("异常的具体原因:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

例子:Hero类的attack方法的isDeadException。

四. 上传代码到GIT

说明:记录一下操作步骤= =,还是不太熟悉。

① 首先在github新建一个仓库Java_Exception_Learn。

然后得到这个仓库的地址(URL),用于IDEA中设置

② 然后在IDEA的项目中设置

  • VCS - 导入到版本控制 - 创建Git存储库:选择要上传的项目
  • 右键项目 - Git - 添加
  • 右键项目 - Git - Commit目录… :弹出窗口,在提交信息输入想备注的东西,然后Commit
  • 继续弹出窗口,点击定义远程,在URL中输入步骤①的URL即可
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值