Java基础-->异常

什么是异常?

异常:异常就是代表程序出现的问题

误区:不是让我们以后不出现异常,而是程序出了异常之后该如何处理


Java基础-->异常_第1张图片

 Error

代表系统级别的错误(属于原重问题)

系统一旦出现问题,sun公司会把这些错误封装成Error对象。Error是给sun公司自己用的,不是给我们程序员用的。因此我们开发人员不用管它。

Excetion

代表程序可能出现问题

我们通常会用Exception以及它的子类类封装程序出现的问题。

运行时异常(RuntimeException)

RuntimeException及其子类,编译阶段不会出现异常提醒。运行时出现异常(数组越界异常)

package 异常;

public class 运行时异常 {
    public static void main(String[] args) {
        /*运行时异常*/
        int[] arr = {0,1,2};
        System.out.println(arr[10]);
        /*Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3
	at 异常.运行时异常.main(运行时异常.java:7)*/
    }
}

编译时异常

编译阶段就会出现的异常提醒(日期解析异常)

package 异常;

import javax.xml.crypto.Data;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class 编译时异常 {
    public static void main(String[] args) throws ParseException {
        /*编译时异常
        * 在编译时期必须手动处理,否则代码报错*/
        String time = "2021年2月1日0";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");

        Data data = (Data) sdf.parse(time);

        System.out.println(data);
    }
}

Java基础-->异常_第2张图片

小结:

  • 异常是什么?
    •  程序中可能出现的问题
  • 异常体系的最上层父类是谁?异常分为几类?
    • 父类:Exception
    • 异常分为两类:编译时异常、运行时异常
  • 编译时异常和运行时异常的区别:
    • 编译时异常:没有继承RuntimeException的异常,直接继承于Exception。编译阶段就会有错误提示
    • 运行时异常:RuntimeException本身和子类。编译时没有错误提示,运行时出现错误;

 运行时异常和编译时异常

编译时异常:编译阶段就要处理的异常(如:日期解析异常)

运行时异常:RuntimeException及其子类,编译阶段不需要处理。代码运行时出现的异常(如:数组越界异常)

Java基础-->异常_第3张图片

 扩展:为什么不将异常归并为一个类?

  • 编译阶段:Java不会运行代码,自会检查语法是否错误,或做出一些性能优化
  • 运行遗产:代码出错导致程序出现的问题

编译时期异常的目的:提醒程序员检查本地信息!

运行时异常和编译时异常的区别

  • 编译时异常:除了RuntimeException和它的子类,其他的都是编译时异常。编译阶段需要进行处理,作用在于提醒程序员。
  • 运行时异常:RuntimeException本身和所有的子类都是运行时异常。【编译阶段不报错,程序运行时报错,是程序运行时出现的。一般是由于参数传递错误带来的问题】

异常的作用

  • 作用1:异常是用来查询bug的关键参考信息
  • 作用2:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况

异常是用来查询bug的关键参考信息

package 异常;

public class Student1 {
    private String name;
    private int age;

    public Student1() {
    }

    public Student1(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student1{name = " + name + ", age = " + age + "}";
    }
}


package 异常;

public class 异常的作用1 {
    public static void main(String[] args) {
        /*作用1:异常是用来查询bug的关键参考信息
          作用2:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
          */
        Student1[] arr = new Student1[3];
        String name = arr[0].getName();
        System.out.println(name);
        /**Exception in thread "main" java.lang.NullPointerException: Cannot invoke "异常.Student1.getName()" because "arr[0]" is null
         at 异常.异常的作用.main(异常的作用.java:10)
         空指针异常*/


    }
}
package 异常;

public class Student2 {
    private String name;
    private int age;

    public Student2() {
    }
    public Student2(String str) {
        String[] arr = str.split("-");
        this.name = arr[0];
        this.age = Integer.parseInt(arr[1]);
    }

    public Student2(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student2{name = " + name + ", age = " + age + "}";
    }
}

package 异常;

public class 异常的作用1_2 {
    public static void main(String[] args) {
          /*作用1:异常是用来查询bug的关键参考信息
          作用2:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
          */
        Student2 stu = new Student2("张三,23");
        System.out.println(stu);
    }
}

异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况

package 异常;

public class Student1 {
    private String name;
    private int age;

    public Student1() {
    }

    public Student1(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        if (age < 18 || age > 40){
            throw new RuntimeException();
        } else
        this.age = age;
    }

    public String toString() {
        return "Student1{name = " + name + ", age = " + age + "}";
    }
}

package 异常;

public class 异常的作用2_1 {
    public static void main(String[] args) {
          /*
          作用1:异常是用来查询bug的关键参考信息
          作用2:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
          */
        /*1、创建学生对象*/
        Student1 s1 = new Student1();
        //年龄:(同学)18-40岁
        s1.setAge(50);
        
        /**
            Exception in thread "main" java.lang.RuntimeException
	        at 异常.Student1.setAge(Student1.java:45)
	        at 异常.异常的作用2_1.main(异常的作用2_1.java:12)*/
    }
}


异常的处理方式

  1. jvm默认处理
  2. 自己处理
  3. 抛出处理

jvm默认处理方式

  • 把异常的名称,异常原因及异常的位置等信息输出在控制台
  • 程序停止执行,下面代码不会再执行
package 异常.异常的处理;

public class JVM默认处理 {
    public static void main(String[] args) {
        /*JVM默认处理异常的方式
        * 1、把异常的名称,异常原因及异常的位置等信息输出在控制台
          2、程序停止执行,下面代码不会再执行*/
        System.out.println("aaa");
        System.out.println("dd");
        System.out.println(1/0);
        System.out.println("vv");
        System.out.println("fdd");
    }
}

aaa
dd
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at 异常.异常的处理.JVM默认处理.main(JVM默认处理.java:10)

自己处理(捕获异常)

目的:当代码出现异常时,程序可以继续执行

格式:

try{

        可能出现异常的代码;

} catch(异常类名 变量名){

        异常的处理代码;

}

package 异常.异常的处理;

public class 自己处理 {
    public static void main(String[] args) {
        /*格式:
        try{
            可能出现异常的代码;
        } catch(异常类名 变量名){
             异常的处理代码;
        }*/

        int[] arr = {1,2,3,4,5};
        try {
            System.out.println(arr[10]);
        } catch (RuntimeException rs){
            System.out.println(rs);
        }
        System.out.println("执行了");

    }
}
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 5
执行了

灵魂四问

  • 如果try中没有遇到问题,怎么执行?
    • 执行try中的全部代码
    • 不执行catch中的代码
package 异常.异常的处理;

public class 自己处理灵魂四问 {
    public static void main(String[] args) {
/*      如果try中没有遇到问题,怎么执行?
        如果try中可能会遇到多个问题,怎么执行?
        如果try中遇到的问题没有被捕获,怎么执行?
        如果try中遇到了问题,那么try下面的其他代码还会执行吗?*/
        int[] arr = {1,2,3,4,5,6} ;
        try {
            System.out.println(arr[0]);
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("索引越界");
        }
        System.out.println("判断是否执行");
    }
}

1
判断是否执行
  • 如果try中可能会遇到多个问题,怎么执行?
    • try中遇到错误程序代码就跳转catch进行匹配
    • 当遇到多个异常时,可以写多个catch进行捕获
    • 当我们捕获多个异常时,如果异常中存在父子关系,父类写最后
package 异常.异常的处理;

public class 灵魂二问 {
    public static void main(String[] args) {
/*
        如果try中可能会遇到多个问题,怎么执行?
*/
        int[] arr = {1,2,3,4,5,6};
        try {
            System.out.println(arr[10]);
            System.out.println(2/0);

        } catch (ArrayIndexOutOfBoundsException e){
            System.out.println("索引越界");
        } catch (ArithmeticException e){
            System.out.println("除数不能为0");
        }
        System.out.println("判断是否执行");

    }
}

索引越界
判断是否执行
  • 如果try中遇到的问题没有被捕获,怎么执行?
    • 程序中断,try相当于没写,代码交给虚拟机处理
package 异常.异常的处理;

public class 灵魂三问 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        try {
            System.out.println(arr[10]);//ArrayIndexOutOfBoundsException
        }catch (NullPointerException e){
            System.out.println("空指针异常");
        }

        System.out.println("检查是否执行");
    }
}
  • 如果try中遇到了问题,那么try下面的其他代码还会执行吗?
    • 不会!
    • 代码直接跳转到catch中进行匹配
    • catch中没有与之匹配将交给虚拟机
package 异常.异常的处理;

public class 灵魂四问 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        try {
            System.out.println(arr[10]);//ArrayIndexOutOfBoundsException
            System.out.println("检查是否执行");
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("空指针异常");
        }
    }
}
空指针异常

Java基础-->异常_第4张图片

Throwable的成员方法

Java基础-->异常_第5张图片

getMessage : 返回此throwable的详细消息字符串

package 异常.异常的处理.Throwable;

public class getMessage {
    public static void main(String[] args) {
        /*getMessage : 返回此throwable的详细消息字符串*/
        int[] arr = {1,2,3,4,5,6};

        try {
            System.out.println(arr[10]);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        System.out.println("检查是否执行");
    }
}
Index 10 out of bounds for length 6
检查是否执行

toString : 返回可抛出的简短描述

package 异常.异常的处理.Throwable;

public class toString {
    public static void main(String[] args) {
        /*toString : 返回可抛出的简短描述*/
        int[] arr = {1,2,3,4,5,6};
        try {
            System.out.println(arr[10]);
        } catch (Exception e) {
            System.out.println(e.toString());
        }
        System.out.println("检查是否执行");
    }
}
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 6

printStackTrace:把异常的信息输出在控制台

package 异常.异常的处理.Throwable;

public class printStackTrace {
    public static void main(String[] args) {
        /*toString : 返回可抛出的简短描述*/
        int[] arr = {1,2,3,4,5,6};
        try {
            System.out.println(arr[10]);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("检查是否执行");
    }
}
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 6
	at 异常.异常的处理.Throwable.toString.main(toString.java:8)
检查是否执行

抛出处理

  • throws :【编译时异常:必须写,运行时异常:可以不写】
    • 写在方法定义处,表示声明一个异常
    • 告诉调用者,使用本方法可能会有那些异常
  • throw:
    • 写在方法内,结束方法。
    • 手动抛出异常对象,交给调用者
    • 方法中下面的代码不再执行

Java基础-->异常_第6张图片

 throw:写在方法内

package 异常.异常的处理;

public class Throw {
    public static void main(String[] args) {
/*      throw:
        写在方法内,结束方法。
        手动抛出异常对象,交给调用者
        方法中下面的代码不再执行
*/
        //需求:定义一个方法求数组的最大值
        int[] arr = null;
        System.out.println(getMax(arr));
        //方法中下面的代码不再执行
        System.out.println("检查是否执行");

    }
    public static int getMax(int[] arr){
        if(arr == null || arr.length == 0 ){
            //手动抛出异常对象,交给调用者
            throw new NullPointerException();
        }
        int max = arr[0];
        for (int a : arr){
            if(a > max){
                max = a;
            }
        }
        return max;
    }
}
Exception in thread "main" java.lang.NullPointerException
	at 异常.异常的处理.Throw.getMax(Throw.java:20)
	at 异常.异常的处理.Throw.main(Throw.java:12)

throws :【编译时异常:必须写,运行时异常:可以不写】

package 异常.异常的处理;

public class Throws {
    public static void main(String[] args) {
/*        throws :【编译时异常:必须写,运行时异常:可以不写】
        写在方法定义处,表示声明一个异常
        告诉调用者,使用本方法可能会有那些异常
*/
        //需求:定义一个方法求数组的最大值
        int[] arr = null;
        try {
            System.out.println(getMax(arr));
        } catch (NullPointerException e) {
            System.out.println("null");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组越界");
        }
        //方法中下面的代码不再执行
        System.out.println("检查是否执行");

    }
    public static int getMax(int[] arr) throws NullPointerException,ArrayIndexOutOfBoundsException{
        int max = arr[0];
        for (int a : arr){
            if(a > max){
                max = a;
            }
        }
        return max;
    }
}
null
检查是否执行

总结:

  • 虚拟机默认处理异常的方式
    • 把异常的信息以红色字体打印在控制台,并结束程序
  • 捕获:try...catch
    • 一般用在调用出,让代码继续往下运行
  • 抛出:throw、throws
    • 在方法中出现异常,方法就没有继续运行的意义,采取抛出处理
    • 让该方法结束运行并告诉调用者出现的问题

Java基础-->异常_第7张图片 


综合练习

Java基础-->异常_第8张图片

 无异常处理:

package 异常;

public class girlfriend {
    private String name;
    private int age;

    public girlfriend() {
    }

    public girlfriend(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "girlfriend{name = " + name + ", age = " + age + "}";
    }
}


package 异常;

import java.util.Scanner;

public class 综合练习 {
    public static void main(String[] args) {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        //创建女朋友的对象
        girlfriend gf = new girlfriend();
        System.out.println("请输入名字");
        //接收名字
        String name = sc.nextLine();
        gf.setName(name);
        //接受年龄
        System.out.println("输入年龄");
        String ageStr = sc.nextLine();
        int age = Integer.parseInt(ageStr);
        gf.setAge(age);
        //打印信息
        System.out.println(gf);
    }
}
请输入名字
sdgf
输入年龄
sdf
Exception in thread "main" java.lang.NumberFormatException: For input string: "sdf"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
	at java.base/java.lang.Integer.parseInt(Integer.java:665)
	at java.base/java.lang.Integer.parseInt(Integer.java:781)
	at 异常.综合练习.main(综合练习.java:18)

Process finished with exit code 1

 增加异常处理:

package 异常;

public class girlfriend {
    private String name;
    private int age;

    public girlfriend() {
    }

    public girlfriend(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        int length = name.length();
        if (length < 3 || length > 10){
            throw new RuntimeException();
        }
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        if(age < 18 || age > 40){
            throw new RuntimeException();
        }
        this.age = age;
    }

    public String toString() {
        return "girlfriend{name = " + name + ", age = " + age + "}";
    }
}
package 异常;

import java.util.Scanner;

public class 综合练习 {
    public static void main(String[] args) {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        //创建女朋友的对象
        girlfriend gf = new girlfriend();
        while (true) {
            try {
                System.out.println("请输入名字");
                //接收名字
                String name = sc.nextLine();
                gf.setName(name);
                //接受年龄
                System.out.println("输入年龄");
                String ageStr = sc.nextLine();
                int age = Integer.parseInt(ageStr);
                gf.setAge(age);
                break;
            } catch (NumberFormatException e) {
                System.out.println("年龄格式错误");
                continue;
            } catch (RuntimeException e){
                System.out.println("姓名长度 或 年龄范围有误");
            }
        }
        //打印信息
        System.out.println(gf);
    }
}

自定义异常

  1. 定义异常类
  2. 写继承关系
  3. 空参构造
  4. 带参构造

Java基础-->异常_第9张图片

 定义异常类

  • 名字错误异常类
  • 年龄错误异常类

名字错误异常类

package 异常.自定义异常;

public class NameFormatException extends RuntimeException {
    //取名技巧
    //NameFormat : 当前异常的名字,表示姓名格式化问题
    //Exception : 表示当前类为异常类

    //运行时 : RuntineEException 核心:表示参数错误导致的问题
    //编译时 : Exception 核心:提醒程序员检查本地信息


    public NameFormatException() {
    }

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

}

年龄错误异常类

package 异常.自定义异常;

public class AgeOutOfBoundsException extends RuntimeException{
    public AgeOutOfBoundsException() {
    }

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

 综合练习修改

package 异常.自定义异常;

public class girlfriend {
    private String name;
    private int age;

    public girlfriend() {
    }

    public girlfriend(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        int length = name.length();
        if (length < 3 || length > 10){
            throw new NameFormatException(name + "格式有误,length < 3 || length > 10");}
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        if(age < 18 || age > 40){
            throw new AgeOutOfBoundsException(age + "不在范围内");
        }
        this.age = age;
    }

    public String toString() {
        return "girlfriend{name = " + name + ", age = " + age + "}";
    }
}
package 异常.自定义异常;

import 异常.自定义异常.girlfriend;

import java.util.Scanner;

public class text {
    public static void main(String[] args) {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        //创建女朋友的对象
        girlfriend gf = new girlfriend();
        while (true) {
            try {
                System.out.println("请输入名字");
                //接收名字
                String name = sc.nextLine();
                gf.setName(name);
                //接受年龄
                System.out.println("输入年龄");
                String ageStr = sc.nextLine();
                int age = Integer.parseInt(ageStr);
                gf.setAge(age);
                break;
            } catch (NumberFormatException e) {
                e.printStackTrace();
            } catch (NameFormatException e){
                e.printStackTrace();
            } catch (AgeOutOfBoundsException e){
                e.printStackTrace();
            }
        }
        //打印信息
        System.out.println(gf);
    }
}

Java基础-->异常_第10张图片

 

你可能感兴趣的:(Java,java,开发语言)