异常Throwable,Exception

异常

异常的概念:

  1. 异常指在程序运行期间,JVM遇到了无法编译的代码,这种情况对于JVM来说就是一种“异常情况”。当玉带这种异常情况,JVM就会在控制太打印“异常信息”,并结束程序。
  2. Java的“异常处理机制”就可以使JVM在遇到“异常代码”时,可以“跳过”有异常的代码,继续执行后续代码。
代码演示:
package com.代码练习.test01;

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

public class Demo01 {
    public static void main(String[] args) {
        //外部进行while死循环,内部输入正确则结束循环。
        while(true) {
            try {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入年龄:");
                int age = sc.nextInt();//假如用户输入的不是int类型,则会出现异常:InputMismatchException
                System.out.println("你的年龄是:"+age);
                break;//
            } catch (InputMismatchException e) {
                //这个地方就可以进行对异常处理并输出提示语:
                System.out.println("输入错误");
            }
        }
        System.out.println("后续代码。。。。");
    }
}

异常的产生过程及JVM默认处理异常的方式

异常产生过程:

  1. JVM执行到有异常的代码;

  2. JVM必须要能够识别出这种异常;

  3. JVM会到类库中找到“描述这个异常的异常类”,并创建对象;

  4. JVM会查看我们的代码是否有catch语句,“捕获”这个异常;

     没有catch语句:就在控制台打印异常信息,然后结束程序;【默认情况】
     有catch语句:跳转到catch语句中,程序就不会结束,会跳过有异常的代码,继续健康的运行下去。
    

JVM默认处理异常的方式:

当出现异常,会在控制台打印“异常信息”,并结束程序。

异常的体系结构及分类

  1. Java内部针对任何Java程序所可能出现的所有“异常情况”都做了定义,并制定了对应的“异常类”。
    很多的异常类,Java内部又进行抽取,最终形成了一套“异常体系结构”
  2. 异常体系结构:
    Throwable(类)
    1. Error错误:不需要晨旭捕获,因为捕获没有意义,程序必须结束。
	package com.代码练习.test02;
	
	import java.util.ArrayList;
	
	public class Demo01 {
	    public static void main(String[] args) {
	        //定义一个int的包装类数组,大概4M左右
	        Integer[] arr = new Integer[1000*1000];
	        //定义一个泛型是Integer类型的集合
	        ArrayList<Integer> inlist = new ArrayList<>();
	        for (int i = 0; i >=0 ; i++) {
	            //在集合中添加arr数组
	            inlist.add(arr[i]);
	            //报错Error:ArrayIndexOutOfBoundsException
	            //原因:无论Java虚拟机的内存有多大,for死循环下,会一直给集合添加4M大小的数组,最终会导致Java虚拟机内存不足。
	        }
	    }
	}
2.  Exception(异常):需要程序处理的,程序运行过程中产生的一些“异常情况”。
		2.1 RuntimeException(运行时异常):指比较低级的异常情况,这种异常是不应该出现的,程序员完全可以通过if判断避免这种异常情况产生,例如:NullPointerException,ArrayIndexOutOfBoundsException
		2.2 除RunTimeException外的其它异常类(编译期异常):指程序员无法事先判断出来,很难预料的异常情况。这种异常情况必须要处理。

异常的处理

try…catch语句的方式处理异常

  1. 异常处理的基本语法:
    try{
    }catch(异常类名 变量名){
    }

  2. 可以捕获到异常的正常情况:

	public class Demo05 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        try {
            System.out.println("请输入年龄:");
            int age = sc.nextInt();
            System.out.println("你的年龄是:" + age);
        }catch (InputMismatchException e){
            System.out.println("你的输入有误!!");
        }
        System.out.println("后续代码......");
    }
}
  1. 不能捕获到异常的情况:
	public class Demo05 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        try {
            System.out.println("请输入年龄:");
            int age = sc.nextInt();//可能出现的是:InputMismatchException异常
            System.out.println("你的年龄是:" + age);

        }catch (NullPointerException e){//而捕获的是:NullPointerException异常,所以此catch无效
            System.out.println("你的输入有误!!");
        }
        System.out.println("后续代码......");
    }
}
  1. 可以捕获所有异常的情况:【不建议】
Scanner sc = new Scanner(System.in);
try {
    System.out.println("请输入年龄:");
    int age = sc.nextInt();//可能出现的是:InputMismatchException异常
    System.out.println("你的年龄是:" + age);

    String s = null;
    System.out.println(s.length());

}catch (Throwable e){//而捕获的是:NullPointerException异常,所以此catch无效
    System.out.println("出现异常!");
}
System.out.println("后续代码......");
	5).建议的写法:
	try {
    Scanner sc = new Scanner(System.in);
    try {
        System.out.println("请输入年龄:");
        int age = sc.nextInt();//可能出现的是:InputMismatchException异常
        System.out.println("你的年龄是:" + age);
    } catch (InputMismatchException e) {
        System.out.println("输入错误!");
    }
    try {
        String s = null;
        System.out.println(s.length());
    } catch (NullPointerException e) {//可能出现NullPointerException异常
        System.out.println("空指针异常!!");
    }

    System.out.println("其他代码....");

}catch (Throwable e){
    System.out.println("程序出现未知异常,请联系系统管理员!!");
    //写日志——将异常信息写入到文件,后期查看这个文件,找到问题,对程序打补丁。
}
System.out.println("后续代码......");

注意:try{}和catch{},在它们的大括号内部定义的变量,只能在那个大括号内部使用。也就是说:在try中定义的变量,在catch中不能使用。finally可以使用

操作异常对象:

当JVM执行try中代码,出现异常时,会识别这个异常,并到类库中找到这个“异常类”,然后创建它的对象,然后判断程序是否有catch来捕获这个异常,有,就执行这个catch——实际上是调用catch方法,JVM会将“异常对象”作为“实参”传入到catch方法。我们可以操作这个异常对象。

常用方法:
  1. public String getMessage();获取异常信息
  2. public String toString();获取异常类名+异常信息
  3. public String printStackTrace(); 获取异常类名+异常信息+错误位置提示。
代码演示:
package com.代码练习.test03;

public class Demo01 {
    public static void main(String[] args) {
        int arr[] = {1,2,3};
        try {
            System.out.println(arr[1]);//正常
            System.out.println(arr[10]);//异常:数组越界
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println("异常了");
            //getMessage()方法:异常信息
            System.out.println("异常信息:"+e.getMessage());
            //toString()方法:异常类名+异常信息
            System.out.println("toString:"+e.toString());
            //printStackTeace()方法:异常类名+异常信息+错误代码提示
            e.printStackTrace();
        }
    }
}

try…catch…catch语句的方式处理异常

  1. 在try{}中,如果某行代码出现异常,try{}中此行代码后面的代码就全部跳过。
  2. 一个try中可能会出现多种异常的情况,可以使用多个catch进行捕获:
    语法:
    try{
    //可能出现异常的代码
    }catch(异常类名1 变量名){
    }catch(异常类名2 变量名){
    }…
    注意:
    1. try中某行代码出异常,try中的后续代码全部跳过。所以通常是“后面的代码”依赖“前面的代码”,如果前面成功,后面被执行,如果前面失败,那么后面也不执行了,这种情况才使用这种try…catch…catch…的语法。
    2. 在“多catch”中,它们没有顺序关系。
    3. 在“多catch”中,使用的“异常类名”通常也是“同级的”;也可以是“子父级”的,但“父级”的异常类型必须放在多catch的末尾。

try…catch…finally语句的方式处理异常

1).语法格式:
try{
}catch(异常类名1 变量名){
}catch(异常类名2 变量名){
}finally{
//无论是否出现异常,都会被执行的代码
}
这种格式,通常用在一个方法中,而且在try和catch中有return 值;语句时,在保证返回前做一些事情,就可以写在finally中。

代码演示:
package com.代码练习.test05;

public class Demo01 {
    public static void main(String[] args) {
        String s = readFile();
        System.out.println("-----------");
        System.out.println(s);
    }

    private static String readFile() {
        try {
            System.out.println("打开文件");//可能出异常
            System.out.println("读取文件"+(10/0));//可能出异常
            return "文件内容";
        }catch (Exception e){
            System.out.println("异常了!!!");
            return null;
        }finally{//无论上面代码是否出现异常,都会执行finally
            System.out.println("关闭文件!");//可能出现异常
            
        }
    }
}

throw抛出异常

  1. throw关键字:表示在方法中可以“抛出一个异常对象”。
  2. 第一种使用情况(图解):
    在这里插入图片描述
  3. 第二种使用情况:
    在这里插入图片描述
    第二种可以自己设置“异常信息”。

throws声明抛出异常【常用】

  1. throws用在“方法声明”处,表示:此方法可能会产生这种异常,如果产生,请JVM将这个异常抛给调用代码。
public class Demo11 {
    public static void main(String[] args) {
        try {
            int[] arr = new int[0];
            int sum = getMax(arr);
            System.out.println("和:" + sum);

        } catch (NullPointerException e) {
            System.out.println("空指针异常!");
        } catch (ArrayIndexOutOfBoundsException e) {

        } catch (ArithmeticException e) {
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static int getMax(int[] arr) throws NullPointerException,
            ArrayIndexOutOfBoundsException,
            ArithmeticException ,Exception{
        int sum = arr[0];//抛出索引越界异常
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        return sum;
    }
}

throw与throws区别:

  1. throw:

     1).用在方法内部;
     2).throw  + (一个)异常对象;
     3).throw 如果抛出的是“运行时异常(RuntimeException)”,调用代码可以不处理,编译可以通过;
     		如果抛出的是“编译期异常(除RuntimeException及其子类以外的其他异常)”,调用的代码必须处理,要么try...catch..,要么继续抛出。
     	常见的“运行时异常”:NullPointerException、ArrayIndexOutOfBoundsException、StringIndexOutOfBoundsException、InputMismatchException
     	常见的“编译期异常”:ParseException(SimpleDateFormae的parse()方法会抛出此异常)
    
  2. throws:

     1).用在方法的“声明处”;
     2).throws + (一个/多个)异常类名(属于声明)
     3).如果声明抛出的是“运行时异常”,调用代码可以不处理,编译可以通过;
       如果声明抛出的是“编译期异常”,调用代码必须处理,要么try...catch...,要么继续抛出。
    
子类重写父类方法时的异常声明:

汇总:无论父类方法是否抛出异常,子类都可以:
1. 可以不抛出任何异常。
2. 可以抛出任何的“运行时异常”;
3. 子类不能抛出跟父类不同的“编译期”异常;(只能抛出跟父类相同的“编译期”异常)

自定义异常:

  1. 当我们写程序时,由于业务逻辑的原因,想抛出一个异常,但类库中并没有相关的“异常类”,这时,我们可以自己来定义“异常类”。
public class Student{
				private int age;
				public void setAge(int age){
					if(age < 15 || age > 50){
						//return;
						throw new 自定义异常对象();
					}
					this.age = age;
				}
			}

  1. 自定义异常类:
    如果继承Exception,就是“编译期”异常;
    如果继承RuntimeException或者它的子类,就是“运行时”异常;
public class AgeException extends Exception {
    public AgeException() {
    }

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

  1. 使用自定义异常:
public class Student {
    private int age;
    public void setAge(int age) throws AgeException {
        if (age < 15 || age > 50) {
            throw new AgeException("异常,年龄必须在15到50之间!");//
        }
        this.age = age;
    }

    public int getAge() {
        return age;
    }
}

  1. 测试类:
public class Demo13 {
    public static void main(String[] args) {
        Student stu = new Student();
        try {
            stu.setAge(100);
        } catch (AgeException e) {//捕获AgeException
            System.out.println("异常信息:" + e.getMessage());
            e.printStackTrace();
        }

        System.out.println(stu.getAge());
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值