Java里的异常详解

1.异常概念

异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响.在程序中的意思就是:

  • 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。

在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。

异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行

2.异常体系和异常分类

3.抛出异常throw

在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。

在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。那么,抛出一个异常具体如何操作呢?

  1. 创建一个异常对象。封装一些提示信息(信息可以自己编写)。

  2. 需要将这个异常对象告知给调用者。怎么告知呢?怎么将这个异常对象传递到调用者处呢?通过关键字throw就可以完成。throw 异常对象。

    throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。

使用格式:

throw new 异常类名(参数);

例如:

throw new NullPointerException("要访问的arr数组不存在");

throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");

public void setAge(int age) {
       if(age<18 || age>=50){
           throw new RuntimeException();
       }else{
           this.age = age;
       }
    }
package yichang;

public class demo01 {
    public static void main(String[] args) {
         /*
            异常作用一:异常是用来查询bug的关键参考信息
            异常作用二:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
        */


        //1.创建学生对象
        Student s1 = new Student();
        //年龄:(同学) 18~40岁
        s1.setAge(50);//就知道了50赋值失败
        //选择1:自己悄悄处理
        //选择2:打印在控制台上

    }
}

4.JVM虚拟机默认处理异常方式

package yichang;

public class demo2 {
    public static void main(String[] args) {

         /*
        JVM默认处理异常的方式:
            1. 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
            2. 程序停止执行,异常下面的代码不会再执行了
        */


        System.out.println("狂踹瘸子那条好腿");
        System.out.println(2/0);//算术异常 ArithmeticException
        System.out.println("是秃子终会发光");
        System.out.println("火鸡味锅巴");

    }
}

JVM默认处理异常的方式:
    1. 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
    2. 程序停止执行,异常下面的代码不会再执行了

5.捕获异常try…catch

如果异常出现的话,会立刻终止程序,所以我们得处理异常:

  1. 该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。

  2. 在方法中使用try-catch的语句块来处理异常。

try-catch的方式就是捕获异常。

  • 捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。

捕获异常语法如下:

try{
     编写可能会出现异常的代码
}catch(异常类型  e){
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}

try:该代码块中编写可能产生异常的代码。

catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。

注意:try和catch都不能单独使用,必须连用。

package yichang;

public class demo3 {
    public static void main(String[] args) {
         /*
            自己处理(捕获异常)
            格式:
                try {
                   可能出现异常的代码;
                } catch(异常类名 变量名) {
                   异常的处理代码;
                }
             好处:可以让程序继续往下执行,不会停止
         */


        int[] arr = {1, 2, 3, 4, 5, 6};
        try{
    //可能出现异常的代码;
    System.out.println(arr[10]);//此处出现了异常,程序就会在这里创建一个ArrayIndexOutOfBoundsException对象
    //new ArrayIndexOutOfBoundsException();
    //拿着这个对象到catch的小括号中对比,看括号中的变量是否可以接收这个对象
    //如果能被接收,就表示该异常就被捕获(抓住),执行catch里面对应的代码
    //当catch里面所有的代码执行完毕,继续执行try...catch体系下面的其他代码
        }catch(ArrayIndexOutOfBoundsException e){
            //如果出现了ArrayIndexOutOfBoundsException异常,我该如何处理
            System.out.println("索引越界了");
        }

        System.out.println("看看我执行了吗?");

    }
}

6.四问

第一问

自己处理(捕获异常)灵魂四问:
    灵魂一问:如果try中没有遇到问题,怎么执行?
会把try里面所有的代码全部执行完毕,不会执行catch里面的代码
注意:
    只有当出现了异常才会执行catch里面的代码
package yichang;

public class demo4 {
    public static void main(String[] args) {
          /*
            自己处理(捕获异常)灵魂四问:
                灵魂一问:如果try中没有遇到问题,怎么执行?
            会把try里面所有的代码全部执行完毕,不会执行catch里面的代码
            注意:
                只有当出现了异常才会执行catch里面的代码


         */
        int[] arr = {1, 2, 3, 4, 5, 6};

        try{
            System.out.println(arr[0]);//1
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println("索引越界了");
        }

        System.out.println("看看我执行了吗?");//看看我执行了吗?

    }
}

第二问

  自己处理(捕获异常)灵魂四问:
        灵魂二问:如果try中可能会遇到多个问题,怎么执行?
会写多个catch与之对应
细节:
    如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面

了解性:
    在JDK7之后,我们可以在catch中同时捕获多个异常,中间用|进行隔开
    表示如果出现了A异常或者B异常的话,采取同一种处理方案
package com.itheima.a01myexception;

public class ExceptionDemo8 {
    public static void main(String[] args) {
            /*
                自己处理(捕获异常)灵魂四问:
                    灵魂二问:如果try中可能会遇到多个问题,怎么执行?
                            会写多个catch与之对应
                            细节:
                                如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面

                            了解性:
                                在JDK7之后,我们可以在catch中同时捕获多个异常,中间用|进行隔开
                                表示如果出现了A异常或者B异常的话,采取同一种处理方案

             */

        //JDK7
        int[] arr = {1, 2, 3, 4, 5, 6};

        try{
            System.out.println(arr[10]);//ArrayIndexOutOfBoundsException
            System.out.println(2/0);//ArithmeticException
            String s = null;
            System.out.println(s.equals("abc"));
        }catch(ArrayIndexOutOfBoundsException | ArithmeticException e){
            System.out.println("索引越界了");
        }catch(NullPointerException e){
            System.out.println("空指针异常");
        }catch (Exception e){
            System.out.println("Exception");
        }

        System.out.println("看看我执行了吗?");







    }
}

第三问

自己处理(捕获异常)灵魂三问:
    如果try中遇到的问题没有被捕获,怎么执行?
    相当于try...catch的代码白写了,最终还是会交给虚拟机进行处理。
package yichang;

public class demo6 {
    public static void main(String[] args) {
  /*
            自己处理(捕获异常)灵魂三问:
                如果try中遇到的问题没有被捕获,怎么执行?
                相当于try...catch的代码白写了,最终还是会交给虚拟机进行处理。
         */



        int[] arr = {1, 2, 3, 4, 5, 6};

        try{
            System.out.println(arr[10]);//new ArrayIndexOutOfBoundsException();
        }catch(NullPointerException e){
            System.out.println("空指针异常");
        }

        System.out.println("看看我执行了吗?");

    }
}

第四问

自己处理(捕获异常)灵魂四问:
    如果try中遇到了问题,那么try下面的其他代码还会执行吗?
    下面的代码就不会执行了,直接跳转到对应的catch当中,执行catch里面的语句体
    但是如果没有对应catch与之匹配,那么还是会交给虚拟机进行处理

package yichang;

public class demo7 {
    public static void main(String[] args) {
/*
            自己处理(捕获异常)灵魂四问:
                如果try中遇到了问题,那么try下面的其他代码还会执行吗?
                下面的代码就不会执行了,直接跳转到对应的catch当中,执行catch里面的语句体
                但是如果没有对应catch与之匹配,那么还是会交给虚拟机进行处理
         */



        int[] arr = {1, 2, 3, 4, 5, 6};

        try{
            System.out.println(arr[10]);
            System.out.println("看看我执行了吗?... try");
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println("索引越界了");
        }

        System.out.println("看看我执行了吗?... 其他代码");

    }
}

7.异常的常见方法

package yichang;

public class demo8 {
    public static void main(String[] args) {
         /*
              public String getMessage()          返回此 throwable 的详细消息字符串
              public String toString()            返回此可抛出的简短描述

              public void printStackTrace()       在底层是利用System.err.println进行输出
                                                  把异常的错误信息以红色字体输出在控制台
                                                  细节:仅仅是打印信息,不会停止程序运行
        */


        int[] arr = {1, 2, 3, 4, 5, 6};
        try {
            System.out.println(arr[10]);
        } catch (ArrayIndexOutOfBoundsException e) {
            String message = e.getMessage();
            //System.out.println(message);//Index 10 out of bounds for length 6
            String string = e.toString();
            //System.out.println(string);//java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 6
            e.printStackTrace();

        }
        //正常的输出语句
        //System.out.println(123);

        //错误的输出语句(而是用来打印错误信息)
        //System.err.println(123);

    }
}

8.声明异常throws


 

package yichang;

public class demo9 {
    public static void main(String[] args) {
        /*
        throws:写在方法定义处,表示声明一个异常。告诉调用者,使用本方法可能会有哪些异常。
        throw :写在方法内,结束方法。手动抛出异常对象,交给调用者。方法中下面的代码不再执行了。


        需求:
            定义一个方法求数组的最大值

*/

        int[] arr = null;
        int max = 0;
        try {
            max = getMax(arr);
        } catch (NullPointerException e) {
            System.out.println("空指针异常");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("索引越界异常");
        }
        System.out.println(max);

    }

    public static int getMax(int[] arr)  throws NullPointerException ,ArrayIndexOutOfBoundsException {
        if(arr==null){
            //手动创建一个异常对象,并把这个异常交给方法的调用者处理
            //此时方法就会结束,下面的代码不会再执行了
            throw new NullPointerException();

        }
        if(arr.length==0){
            throw new ArrayIndexOutOfBoundsException();
        }



        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }
}

9.练习

package lx;

import java.util.Scanner;

public class demo1 {
    public static void main(String[] args) {
          /*
            需求:
                键盘录入自己心仪的女朋友姓名和年龄。
                姓名的长度在 3 - 10之间,
                年龄的范围为 18 - 40岁,
                超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
            提示:
                需要考虑用户在键盘录入时的所有情况。
                比如:录入年龄时超出范围,录入年龄时录入了abc等情况
        */
        Girlfriend g = new Girlfriend();
        Scanner sc = new Scanner(System.in);
        while (true) {
            try {
                System.out.println("请输入你心仪的女朋友姓名");
                String name = sc.nextLine();
                g.setName(name);
                System.out.println("请输入你心仪的女朋友年龄");
                String str = sc.nextLine();
                int age = Integer.parseInt(str);
                g.setAge(age);
                break;//程序前面的只要出现异常就会跳到对应的catch语句体当中
            } catch (NumberFormatException e) {
                System.out.println("输入的年龄格式错误");
            } catch (RuntimeException e) {
                System.out.println("年龄或者名字的范围不对");

            }
        }


    }
}

package lx;

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) {
        //  姓名的长度在 3 - 10之间,

        if (name.length() < 3 || name.length() > 10) {
            throw new RuntimeException();//运行出错误 运行时错误可以不用写throws
        }
        this.name = name;
    }

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

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        // 年龄的范围为 18 - 40岁
        if (age < 18 || age > 40) {
            throw new RuntimeException();

        }
        this.age = age;
    }

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

10.自定义异常

 

package lx;

import java.util.Scanner;

public class demo2 {
    public static void main(String[] args) {
        //技巧:
        //NameFormat:当前异常的名字,表示姓名格式化问题
        //Exception:表示当前类是一个异常类


        //运行时:RuntimeException 核心 就表示由于参数错误而导致的问题
        //编译时:Exception 核心 提醒程序员检查本地信息
          /*
            需求:
                键盘录入自己心仪的女朋友姓名和年龄。
                姓名的长度在 3 - 10之间,
                年龄的范围为 18 - 40岁,
                超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
            提示:
                需要考虑用户在键盘录入时的所有 情况。
                比如:录入年龄时超出范围,录入年龄时录入了abc等情况
        */
        Girlfriend g = new Girlfriend();
        Scanner sc = new Scanner(System.in);
        while (true) {
            try {
                System.out.println("请输入你心仪的女朋友姓名");
                String name = sc.nextLine();
                g.setName(name);
                System.out.println("请输入你心仪的女朋友年龄");
                String str = sc.nextLine();
                int age = Integer.parseInt(str);
                g.setAge(age);
                break;//程序前面的只要出现异常就会跳到对应的catch语句体当中
            } catch (NumberFormatException e) {
              e.printStackTrace();
            } catch (AgeFormatExcepion e) {
                e.printStackTrace();

            } catch (NameFormatExcepion e) {
                e.printStackTrace();
            }

        }
    }
}
package lx;

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

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

package lx;

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值