异常类

1.异常机制概念:


package 异常机制;

public class Test1 {
    public static void main(String[] args) {
        /*
        * 在java中,对于遇到的问题,有一个类来描述:
        * Throwable是Exception和Error的父类,是顶级父类
        *
        * */
//        Exception用来描述一般性的问题异常,可以解决
        /*对于异常也分为两种:
        * (1)编译期异常:必须解决,不解决程序无法运行
        * (2)运行期异常:可以解决,也可以不解决.
        * */

//        Error 错误,描述严重性问题错误,我们无法解决,比如内存溢出




//        Throwable是Exception和Error的父类,Excepiton类是可以解决的异常类,Error类不能解决,Exception类的子类一为发生在编译期异常的异常(为非RuntimeException类及其子类,),这样的异常必须解决,否则编译器无法运行,二为运行期异常(为RuntimeException类及其子类),发生在运行期间,其异常可以解决,也可以不解决
    }
}
package 异常机制;

public class Test3 {
    public static void main(String[] args) {
//        Throwable 类是 Java 语言中所有错误或异常的超类(顶级类)。
    /*   运行期异常(为RuntimeException类及其子类):可以解决,也可以不解决.
   */
    int a=10;
    int b=0;
//    ArithmeticException:运行期异常,算数异常,为RuntimeException子类
      //  System.out.println(a/b);
        /*运行期异常,你可以选择处理,也可以选择不处理,上面这段代码,你并没有对这段代码进行处理,你没有处理,JAVA就是用的默认处理方式
        * 默认处理方式是真么处理的?
        * 当遇到异常时JAVA虚拟机会打印异常的堆栈信息,然后会退出JAVA虚拟机,加入这个语句下面还有代码,后面的代码就不会执行了
        * 也就是说JAVA虚拟机默认处理运行期异常的方式不够友好,如果你觉得这种方式不好,你可以自己去处理运行期异常:
        *=======================================================================================================
        * */
//        自己处理这个运行期异常:遇到问题了,我们可以自己提示异常信息,但是不退出虚拟机,让代码继续往下执行,那怎么处理呢?
//        使用关键字:try catch,使用了之后Java就不会自动处理异常了,转变为try和catch里面的方法处理异常
//        如:这个如果让JAVA自己处理就会报异常并且退出虚拟机
        //  System.out.println(a/b);那如果我们自己处理,方法是这样的:
        try {
            System.out.println(a/b);  //try里面是放的可能会出现异常的一句,如果有异常了就马上进入catch语句,执行catch里面的语句
        }
        catch ( ArithmeticException aa){//catch括号里面放的是捕获何种类型的异常类+形参名,这个类是提前要确认好的,大括号里面放的是:
//            一旦你出现这种异常,你的处理逻辑是啥
//            如果没有出现你要捕获的异常类型,那么catch里面的代码不会执行,记住了.catch里面的异常类一定要和try对应的异常要对应上,如果不一致,则最后还是交给虚拟机自动处理了,所以发生的异常要和捕获的异常类要一致
            System.out.println("除数不能为0");
        }
//        这样的话后面的语句会继续执行
        System.out.println("111111111111111111");
        System.out.println("111111111111111111");
        System.out.println("111111111111111111");
        System.out.println("111111111111111111");
        System.out.println("111111111111111111");
        System.out.println("111111111111111111");

    }
}
package 异常机制;

public class Test4 {
    public static void main(String[] args) {
//        运行期异常
        int[] arr={20,30};
        int a=10;
        int b=0;
        arr=null;
      //  System.out.println(a/b);
       // System.out.println(arr[3]);//运行期异常 :ArrayIndexOutOfBoundsException(角标越界异常)
//        用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
//        遇到异常,如果是默认处理方式的话,后面的语句不再回运行
        try {
            System.out.println(a/b);//如果是只有一个catch的情况下,则try只会执行到出现第一个异常的语句就进了catch了,如果恰巧那个catch的参数不是对应的异常类的,则直接交给虚拟机自动处理异常,下面的代码都不会执行到
//            还是上述这种情况,如果正好catch的异常类对应的是try的异常,那么就会执行catch里面的语句,但是try中的出现异常语句下面的那些语句就不会执行了
//            如果说try中可能会有多个异常,你都想处理掉,那么就用多个catch就可以了.但是还是一个意思,只要成功try了其语句中的一个异常,那么try代码块中出现异常问题的下面的语句都不会在执行了
//            所以最好在try的时候把所有可能出现的异常都catch到,后面就不会有事了,异常处理完了,trycatch后面的代码该咋执行咋执行
/*注意:
* try里面要放的是有可能出现问题的代码,对于没有可能出现问题的代码就不要往里面放了,会影响性能
* 还有一点啊,语法错误跟异常没关系
* */
            System.out.println(arr[3]);
        }
        catch (ArithmeticException aa){
            System.out.println("除数不能为0!");
        }
        catch (ArrayIndexOutOfBoundsException bb){
            System.out.println("角标有问题了!");
        }catch (NullPointerException n){
            System.out.println("空指针异常");
        }catch (Exception e){//如果是不太清楚其中会出现什么异常,那直接上顶级异常就可以了,它包括了所有的异常(记住就行了,就这么理解),拿不准的时候就写这个就行,这个可以写,但是最好不要这样写,能明确的异常一定要写明确,实在不知道的就只能用这个最终的大异常了,这样写不太规范,如果只写一个这个,但是如果出现异常了,你不能明显分辨到底是什么异常
            /*注意:
            * 如果捕获的多个异常中有父子类继承关系,父类异常要放到最后,并列关系的异常(即共同继承一个父类异常类)谁前谁后无所谓
            * */
            System.out.println("其他异常");
        }
    }
}
package 异常机制;

public class Test5 {
    public static void main(String[] args) {
//        JDK1.7以后提供了一种捕获多种异常的语法,不推荐,了解(pass掉)
        int[] arr={20,30};
        int a=10;
        int b=0;
        arr=null;
       try{
           System.out.println(a/b);
       }catch (ArrayIndexOutOfBoundsException|ArithmeticException|NullPointerException e){//不能写父子关系类异常,只能写并列关系类异常,且这种方法不好,因为你最终也无法判断到底是哪种异常,当然可以通过if语句去判断具体是哪种异常,但是这样太麻烦了,还不如用之前的方法
           if(e instanceof  ArithmeticException)
           {System.out.println("分母不能为0");
       }else if(e instanceof  ArrayIndexOutOfBoundsException){
            System.out.println("角标越界");
        }else if(e instanceof  NullPointerException){
               System.out.println("空指针异常");}
       }
        System.out.println("=======================");
        System.out.println("=======================");
        System.out.println("=======================");
        System.out.println("=======================");
        System.out.println("=======================");
        System.out.println("=======================");
    }
}
package 异常机制;

import java.util.Scanner;

public class test6 {
    public static void main(String[] args) {
//        finally:
        int a = 10;//(ctrl+shift+方向键能上下移动这行代码)
        int b=0;
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入第一个整数");
        int i = scanner.nextInt();
        int i1 = scanner.nextInt();
        try {
            System.out.println(a/2);
            System.out.println(i/i1);
        }catch (ArithmeticException aa){
            System.out.println("除数不能为0");
        }finally {
//            finally关键字表示 不管try里面的代码不管有没有遇到异常,即不管遇没遇到异常,finally里面的代码一定会执行,对于一些没有trycatch的语句同样适用
            System.out.println("zhixingle");
//            一般会在finally里面写善后收尾的代码,做一些善后工作,比如善后资源:
            if(scanner!=null){//这写的比较全,主要是考虑scanner是成员变量且初始值为null时,方法中new对象,但是在new对象前的一个语句为异常语句,这样的话下面的语句就不会执行了,是预防这样的情况发生
                scanner.close(); //释放资源,类似叫java垃圾回收器回收的那个语句一样
            }

        }

    }
}
package 异常机制;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
//就记住一句话就完事了:只要是这个个方法体重出现了异常机制,如果使用throws的话就在这个方法的声明后面new 该异常类就行,然后方法A在调用了这个方法,如果还是想抛出异常的话,继续在方法A的后面throws该异常类,一般工具类的方法都是直接throws,到了main方法里面才会选择trycatch手动处理,一般只有编译期异常才会选择throws或者trycatch,运行期异常一般不处理或者trycatch
public class Test7 {
    public static void main(String[] args) /*throws ParseException*/ {//main方法使用或者调用其代码块儿中的变量或方法
//        编译期异常:发生在编译期间(非RunTimeException及其子类),编译期异常必须手动处理,不处理程序就无法运行
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//日期类转换为日期字符串
        String format = simpleDateFormat.format(date);
        System.out.println(format);
//        日期字符串转换为日期类
        String date1 = "2020-07-04 21:04:57";
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     //   Date parse = simpleDateFormat1.parse(date1);//在这里就是编译期异常,必须要手动处理,不然程序就无法运行了,这里抛出了异常,抛给了调用这个方法的地方(这里指main方法),在这里是main调用这个语句,所以抛给了main方法
//        上面这个是把字符串日期类转换为日期类
//        处理编译期异常有两种方式:
//        方式一:
// 使用throws向上抛出,抛给调用者去处理,谁调用谁处理,俗称甩锅,注意这里是throws,语句在main方法中执行,所以main方法调用这条语句,但是main方法是由Java虚拟机去调用的,所以最终是由虚拟机处理
//        最后甩锅给虚拟机后,跟之前的那些没有trycatch的异常一样,完全一样,很暴力
//方式二:
//        使用try catch捕获处理,用catch处理语句
        try {
            Date parse = simpleDateFormat1.parse(date1);
        }catch (ParseException p){
            System.out.println("解析失败");//手动解决的
        }

    }
}
package 异常机制;

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

public class Test8 {
    public static void main(String[] args)  {
        String date="2020-08=-04 21:04:57";
        try {
            Date date1 = parseDate(date);

        } catch (ParseException e) {
            System.out.println("日期异常");
        }
    }

    private static Date parseDate(String date) throws ParseException {//(只要不是RunTimeException类及其子类的异常类就是编译期异常)
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date parse = simpleDateFormat1.parse(date);//这里抛异常给了parseDate方法,因为parseDate方法调用这个方法,然后main方法又调用parseDate方法,所以在main方法里就需要在处理,有那两种方式,如果选方式一就继续向上抛,最终抛给了虚拟机
        return parse;
//        编译期异常,抛出的话可以抛给调用者,谁调用谁就处理这个异常,但是一般抛到main方法里面就不在抛了,因为main方法在抛的话抛给虚拟机了,虚拟机处理异常方式不太友好,所以抛到mian方法中的话一般用try catch处理
    }
}
package 异常机制;


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

public class Test9 {
//工具类里面的异常直接抛出去,不要抓,让调用这个方法的方法去想办法处理异常
    private Test9(){};
    public static Date psraseDateStr(String dateStr,String formate) throws ParseException {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat(formate);
        Date parse = simpleDateFormat1.parse(dateStr);//这里就有异常,一般在工具类类里面就直接抛出异常就完事了,交给调用这个方法的方法去处理
        return parse;
    }
//工具类里面的异常就抛出去就可以了,不用自己抓,抛给调用工具类的方法去处理

}

2.自定义异常

package 异常机制.自定义异常;

import java.util.Scanner;

public class Test {
      static   double money=100;
    public static void main(String[] args) {
//        在我们开发项目中,会遇到各种各样的异常,Java给我们提供的异常类并不能完全描述我们遇到的各种异常
//        比如面部识别异常,指纹识别异常
//        对于Java中没有提供的异常,但是我们业务需求要用这种异常,那么我们可以自定义异常
//        如定义余额不足异常:
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入您的取款金额");
        double v = scanner.nextDouble();
        quQuan(v);


    }

    private static void quQuan(double v) {
        if(money<=v){//如果是正常情况的话,正常取钱
            money-=v;
            System.out.println("取款成功");
        }else {
          //如果取得比存得多的话,就不是正常情况,就要抛出一个异常,不让程序执行,程序终止
            throw new NoMoneyException("余额不足");
        }
        money-=v;//如果负数的话,就要抛出一个异常

    }
}
package 异常机制.自定义异常;

public class NoMoneyException extends RuntimeException{//只要把我们自定义的类纳入到RuntimeException异常类体系中,成为其子类,就是一个异常类了,妙啊,构造方法直接全部继承父类的就行了,如果你方法内部想定义有参,则这里的构造方法须调用父类有参构造,如果直接用无参,则就直接调用无参构造就行了
//    余额不足的类

    public NoMoneyException() {
    }//这里默认不写东西,直接就调用父类的无参构造

    public NoMoneyException(String message) {
        super(message);//子类继承父类,在子类的构造方法内部一定先执行父类的构造方法,默认优先执行父类无参的,如果想执行父类有参的或者父类没有无参的构造方法,也可在子类构造方法中调用父类有参的构造方法


    }
}
package 异常机制.自定义异常;

public class MyTest {
    public static void main(String[] args) {
//子类在重写父类方法时:
// (1)如果父类方法没有抛出过异常,则子类不能抛出异常,如果子类遇到了异常,则直接内部try catch
//        (2)子类不能抛出父类没有抛出过的异常,子类抛出的异常数量只能比父类少或者一样,不能比父类大,
// (3)子类抛出的异常类的范围只能比父类的小,或者一样
        // (4) 子类在重写父类方法时,如果父类方法有抛出异常,则子类可以选择抛,也可以选择不抛,在内部处理。


    }
}

class Fu{
    public void show() throws RuntimeException{

    }
}
class Son extends Fu {
    @Override
    public void show() throws  NullPointerException {
        super.show();
    }
}

3.异常的快捷键方式:

package 异常机制.自定义异常.异常快捷键搞定;

public class Test {
    public static void main(String[] args) {
//        方式一:
//        ctrl+alt+t快捷键:自动异常处理(所选中的这一行代码没有任何注释的时候才能用这个方法)
        try {
            System.out.println(1/0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(1/0);
        //ctrl+w 选中这一行代码
//  或者对写完之后的语句 ;后面.try,也可以自动补全了
        try {
            System.out.println(1/0);
        } catch (Exception e) {
            e.printStackTrace();
        }
//        方式二: 在分号前的语句用.try也可以自动生成异常语句
        try {
            System.out.println(1/0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//对于编译期异常,就按alt+enter选择要么捕获要么抛出
//总结就是:对于运行期异常,可处理,也可不处理,如果处理只有一种方式:try catch在加个finally
//对于编译期异常:就一定要处理,对应处理方式有两种:一种是 try catch 加finally 另一种是throws 或在方法体内部throws,throws和throw这两种区别已总结过
//编译期异常IDEA一定会提示你,因为不处理程序就运行不了,这个时候按照之前的处理方式处理,运行期异常IDEA不会提醒你,因为运行期异常可处理,也可不处理,你需要自己去留心哪个语句会出问题,然后try catch就可以,当然你也可以不处理,那样就会交给JAVA虚拟机处理,它的方式很暴力,不建议用

4.异常处理

package 异常机制.异常处理;
//异常处理的方法
public class Test {
    public static void main(String[] args) {
        int a=10;
        int b=0;
        try {
            System.out.println(a/b);
        }catch (ArithmeticException aa){//这里是对异常方式的处理
            System.out.println("除数为0");//对异常方式的处理不要用空处理(就是什么都不写),哪怕只是一句输出语句的提示都可以
            aa.printStackTrace();//打印异常信息的堆栈信息,一般异常处理方式只选这一个就行了,别的不用选
            aa.getMessage();//可以查看异常的名称
            System.out.println(aa.toString());
        }
    }
}
package 异常机制.异常处理;

import java.util.InputMismatchException;
import java.util.Scanner;

public class Test1 {
    public static void main(String[] args) {
//        有时候出现异常不是仅仅为了打印异常信息,知道这有了异常了,有时候出现异常还是为了去做一个判断,比如
        while (true) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入整数");
            try {

                int i = scanner.nextInt();
                break;//输入对了,就继续走try下面的代码,且跳过catch语句,执行catch语句下面的语句
            } catch (InputMismatchException i) {
                System.out.println("输的不对重新输");
            }//这个就是输入类型不跟规定类型一致时出现的异常,如果输错了,那么就执行catch中的方法,执行完在执行下面的方法,发现时循环,然后就继续执行循环
//            这个方法跟之前那个 hasnextInt()方法一样
        }

    }
}
package 异常机制.异常处理;

import java.util.Scanner;

public class Test2 {
//    throw和throws区别:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!精髓,记住!
//    相同点:
//    他俩都可以进行异常的抛出
//    不同点:
//    throws是用在方法声明后面,throw是用在方法内部抛出异常
//    throws可以跟多个异常类名,用逗号隔开,throw只能抛出一个异常对象名
//    throws表示抛出异常,由该方法的调用者来处理,throw表示抛出异常,由其在的方法体内的语句来处理(一般就是在构造方法里面输点跟异常类有关的语句)
//    throws表示出现异常的一种可能性,并不一定会出现这些异常。throw则是抛出了异常,执行了throw表示一定出现了异常
//    当然throw和throws可以同时用,即使throw和throws抛出的异常完全一样都可以
//    例如:
public static void main(String[] args)/*throws ArithmeticException*/ {
    Scanner scanner = new Scanner(System.in);
    int i = scanner.nextInt();
    int i1 = scanner.nextInt();
    int r=test(i,i1);
}

    private static int test(int i, int i1) /*throws ArithmeticException*/{//方法上可以直接用throws抛异常,当然,如果你愿意,你可以在任何方法上抛任何异常,一般只在出现异常的工具类的方法上抛异常
        int aa=0;
        if(i1==0){
//            如果除数为0,直接就抛出异常
            throw  new ArithmeticException("分母为0了");//这里如果写有参构造的话,异常的那个红字里面就会把这个参数打印出来
//            这里经过判断之后主动抛出异常,让程序不在往下执行,其后果于throws一样
        }else {
           aa=i/i1;
        }
        return aa;
    }
}
//final 是修饰字符:修饰类不能被继承,修饰方法,方法能被继承但不能被重写,修饰常量时,常量不能被修改
//finally是try catch 的后备语句,当有善后工作要做时,就用finally,用fially时,不管异常有没有触发,finally都会执行其代码块儿
//finalize是Object类里面的一个方法,用于垃圾回收器的回收

//只要有return的地方,就会将其所在的方法结束掉,因此只要方法里面有个return,就去看其所在的方法,就知道这个方法结束了
//哪里看到虚拟机退出,后面的代码管你是return还是finally都不会在执行了
//当看到catch{
//            sout("asdsdsad");
//             return;
//             }
//              finally{
//            sout("123");
// }
//问:finally的语句会执行嘛?会,只要不是虚拟机退出,遇到这种情况,会先执行finally,在执行return,因为不管异常发没发生,都要执行finally,加了个return的话也得是这样,不然return完了没执行finally,矛盾了,所以会先执行finally,在return.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值