Java异常处理机制, ,超详细整理,适合新手入门

在这里插入图片描述

1.异常入门

虚拟机错误
栈溢出
内存溢出
检查时异常
运行时异常
1/0
Throwable
Error
Exception
VirtulMachineError
AWTError
StackOverFlowError
OutOfMemoryError
IOException
RuntimeException
EOFException
FileNotFoundException
ArithmeticException
MissingResourceException
ClassNotFoundException
NullPointerException
UnKnowType
下标越界异常

Shortcuts:选中代码块->快捷键->Ctrl+Alt+t (Surround with)
在这里插入图片描述
改正之后:

public class Exception01 {
    public static void main(String[] args) {
        int num1 = 1;
        int num2 = 0;
        try {
            int num3 = num1 / num2;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        System.out.println("程序执行完成……");
    }
}

2. Throwable类的异常体系图

  1. 体现了继承和实现关系:实线是继承,虚线是实现。
    在这里插入图片描述
  2. 运行时异常一般指编程时的逻辑错误,编译器检测不出;
  3. 编译时异常,是编译器要求必须处理的异常;
    !](https://img-blog.csdnimg.cn/8b22acba4d3d457f848008da082151f2.png)

2.1 NullPointerException

Exception in thread “main” java.lang.NullPointerException
at com.zzw.exception_.NullPointerException_.main(NullPointerException_.java:10)

public class NullPointerException_ {
    public static void main(String[] args) {
        String name = null;
        System.out.println(name.length());
    }
}

2.2 ArithmeticException

Exception in thread “main” java.lang.ArithmeticException: / by zero
at com.zzw.exception_.NullPointerException_.main(NullPointerException_.java:11)

public class NullPointerException_ {
    public static void main(String[] args) {
        int num1 = 1;
        int num2 = 0;
        int num3 = num1 / num2;
    }
}

2.3 ArrayIndexOutOfBoundsException

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 3
at com.zzw.exception_.NullPointerException_.main(NullPointerException_.java:11)

public class NullPointerException_ {
    public static void main(String[] args) {
        int[] arr = new int[3];
        for (int i = 0; i <= arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

2.4 ClassCastException

Exception in thread “main” java.lang.ClassCastException: com.zzw.exception_.B cannot be cast to com.zzw.exception_.C
at com.zzw.exception_.NullPointerException_.main(NullPointerException_.java:11)

public class NullPointerException_ {
    public static void main(String[] args) {
        A a = new B();//向上转型
        B b = (B)a;//向下转型
        C c = (C)a;//不允许,抛异常
    }
}
class A {}
class B extends A {}
class C extends A {}

2.5 NumberFormatException数字格式不正确异常

当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换成适当格式时,抛出该异常。

Exception in thread “main” java.lang.NumberFormatException: For input string: “赵志伟”
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at com.zzw.exception_.NumberFormatException_.main(NumberFormatException_.java:15)

public class NumberFormatException_ {
    public static void main(String[] args) {
        String nums = "1234";//正确
        String name = "赵志伟";
        //将String转成int
        int i1 = Integer.parseInt(nums);
        int i2 = Integer.parseInt(name);
        System.out.println(i1);//1234
    }
}

3. try-catch-finally

如果没有使用finally,语法是可以通过的;

在这里插入图片描述

3.1 try-catch细节

1.如果发生了异常,则异常之后的代码不会执行,直接进入catch块

public class TryCatchDetail {
    public static void main(String[] args) {
        try {
            String str = "zzw";
            int a = Integer.parseInt(str);
            System.out.println("数字:" + a);
        } catch (NumberFormatException e) {
            System.out.println("报错信息:" + e.getMessage());
        }
        System.out.println("程序继续执行");
    }
}
输出:报错信息:For input string: "zzw"
程序继续执行

2.如果异常没有发生,则顺序执行try代码块,不会进入到catch代码块

public class TryCatchDetail {
    public static void main(String[] args) {
        try {
            String str = "123";
            int a = Integer.parseInt(str);
            System.out.println("数字:" + a);
        } catch (NumberFormatException e) {
            System.out.println("报错信息:" + e.getMessage());
        }
        System.out.println("程序继续执行");
    }
}
输出:数字:123
程序继续执行

3.如果希望不管是否发生异常,都执行某段代码(关闭连接、释放资源),放在finally代码块内;

public class TryCatchDetail {
    public static void main(String[] args) {
        try {
            String str = "zzw";
            int a = Integer.parseInt(str);
            System.out.println("数字:" + a);
        } catch (NumberFormatException e) {
            System.out.println("报错信息:" + e.getMessage());
        } finally {
            System.out.println("finally代码块被执行");
        }
        System.out.println("程序继续执行");
    }
}
输出:
报错信息:For input string: "zzw"
finally代码块被执行
程序继续执行
public class TryCatchDetail {
    public static void main(String[] args) {
        try {
            String str = "123";
            int a = Integer.parseInt(str);
            System.out.println("数字:" + a);
        } catch (NumberFormatException e) {
            System.out.println("报错信息:" + e.getMessage());
        } finally {
            System.out.println("finally代码块被执行");
        }
        System.out.println("程序继续执行");
    }
}
输出:
数字:123
finally代码块被执行
程序继续执行

4.如果try代码块内有多个异常,可以使用多个catch 分别捕获不同的异常,相应处理;
4.1 要求子类异常写在前面,父类异常写在后面;

public class TryCatchDetail02 {
    public static void main(String[] args) {
        try {
            Person person = new Person();
            person = null;
            //NullPointerException
            System.out.println("person的名字:" + person.getName());
            int num1 = 1;
            int num2 = 0;
            //ArithmeticException
            int res = num1 / num2;
        } catch (NullPointerException e) {
            System.out.println("空指针异常->" + e.getMessage());
        } catch (ArithmeticException e) {
            System.out.println("算术异常->" + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println();
        }
    }
}
输出:
空指针异常->null

3.2 try-finally

try-finally可以配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉、退出;
应用场景:就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑;

public class TryCatchDetail03 {
    public static void main(String[] args) {
        try {
            int n1 = 10;
            int n2 = 0;
            int res = n1 / n2;
        } finally {
        	//这里会执行.....
            System.out.println("执行了finally");
        }
        //这里不会执行.....
        System.out.println("程序继续执行……");
    }
}
输出:
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.zzw.try_.TryCatchDetail03.main(TryCatchDetail03.java:12)
执行了finally

3.3 练习

finally必须执行, 即使前面存在return

public class TryCatchExercise01 {
    public static void main(String[] args) {
        System.out.println(method());//4
    }
    public static int method() {
        try {
            String[] names = new String[3];
            //names[1] = null
            if(names[1].equals("tom")) {//空指针异常
                System.out.println(names[1]);
            } else {
                names[3] = "zzw";//数组越界
            }
            return 1;
        } catch (ArrayIndexOutOfBoundsException e) {
            return 2;
        } catch (NullPointerException e) {
            return 3;//很遗憾, 这里不会执行, 即不会返回3
        } finally {//因为finally必须执行
            return 4;//所以会在这里返回4
        }
    }
}

TryCatchExercise02 .java

public class TryCatchExercise02 {
    public static void main(String[] args) {
        System.out.println(method());
    }
    public static int method() {
        int i = 1;
        try {
            i++;//2
            String[] names = new String[3];
            if(names[1].equals("tom")) {//空指针异常
                System.out.println(names[1]);
            } else {
                names[3] = "zzw";
            }
            return 1;
        } catch (ArrayIndexOutOfBoundsException e) {
            return 2; //这里不会执行
        } catch (NullPointerException e) {
            return ++i;//这里不会返回, 但++i还是要执行 i=3
        } finally {//必须执行
            return ++i;//4
        }
    }
}
输出:
4

TryCatchExercise03.java

public class TryCatchExercise03 {
    public static void main(String[] args) {
        System.out.println(method());
    }
    public static int method() {
        int i = 1;//i=1
        try {
            i++;//i=2
            String[] names = new String[3];
            if (names[1].equals("tom")) {//空指针异常
                System.out.println(names[1]);
            } else {
                names[3] = "zzw";
            }
            return 1; //这里不会执行
        } catch (ArrayIndexOutOfBoundsException e) {
            return 2; //这里不会执行
        } catch (NullPointerException e) {
            //++i执行 i=3, 因为有finally, 即return不会马上执行
            //又因为finally没有return语句
            //所以底层通常是把这里要返回的 i => 保存到临时变量 temp, 即 temp = 3;
            //然后执行finally语句, 最后返回临时变量
            return ++i;
        } finally {//必须执行
            ++i;//i=4
            System.out.println("i=" + i);//i=4
        }
    }
}
输出:
i=4
3

小结
1)如果没有出现异常, 则执行try块中所有语句, 不执行catch块中语句. 如果有finally, 最后还需要执行finally里面的语句.

2)如果出现异常, 则try块中异常发生后, try块剩下的语句不再执行, 将执行catch块中的语句, 如果有finally, 最后还需要执行finally里面的语句!


TryCatchExercise04 .java 如果用户输入的不是一个整数, 就提示他反复输入, 直到输入一个整数

public class TryCatchExercise04 {
    public static void main(String[] args) {
        method();
    }
    public static void method() {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入一个整数: ");
        String num = scanner.nextLine();
        try {
            Integer.parseInt(num);
        } catch (NumberFormatException e) {
            System.out.println("==========输入错误, 请重新输入==========");
            method();
        }
    }
}

4. throws

如果没有显示的使用try-catch,默认使用throws方法;

在这里插入图片描述

注意事项和细节

1.对于编译异常,程序必须处理;(比如:FileNotFoundException);

public class Throw01 {
    public static void main(String[] args) {
        
    }
    public void f1() throws FileNotFoundException,NullPointerException,ArrayIndexOutOfBoundsException {
        //这里的异常FileInputStream 是编译异常
        //1.方法一,可以使用try-catch
        //2.方法二,可以使用throws抛出异常,让调用f1()方法的调用者(方法)处理
        //3.throws关键字后,也可以跟异常列表,即可以跟多个列表
        FileInputStream fileInputStream = new FileInputStream("D://a.txt");
    }
    public void f2() throws Exception {
        //这里的异常FileInputStream 是编译异常
        //1.方法一,可以使用try-catch
        //2.方法二,可以使用throws抛出异常,让调用f1()方法的调用者(方法)处理
        FileInputStream fileInputStream = new FileInputStream("D://a.txt");
    }
}

2.对于运行异常,程序中如果没有处理,默认就是throws方式处理;

public class ThrowDetail {
    public static void main(String[] args) throws ArithmeticException{
        f2();
    }
    public static void f2() throws ArithmeticException{
        int n1 = 1;
        int n2 = 0;
        int res = n1 / n2;
    }
}

3.在继承中对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类此方法抛出的异常类型一致,要么为父类抛出异常类型的子类型;
子类重写方法的异常抛出类型必须和父类的异常类型相同或为其子类;

class Father {
    public void method() throws RuntimeException { }
}
class Son extends Father {
    @Override
    public void method() throws NullPointerException {
        super.method();
    }
}

课后练习

调用f2()报错,因为f2()抛出的是编译异常
解决方案一:throws抛出异常

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

    }
    public static void f1() throws FileNotFoundException {
        //1.因为f2()方法抛出的是一个编译异常
        //2.解决方案:throws抛出异常
        //3.try-catch
        f2();
    }
    public static void f2() throws FileNotFoundException {
        FileInputStream fileInputStream = new FileInputStream("D://a.txt");
    }
}

解决方案二:try-catch

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

    }
    public static void f1() throws FileNotFoundException {
        //1.因为f2()方法抛出的是一个编译异常
        //2.解决方案:throws抛出异常
        //3.try-catch
        try {
        	f2();
        } catch(FileNotFoundException e) {
        	e.printStackTrace();
        }
    }
    public static void f2() throws FileNotFoundException {
        FileInputStream fileInputStream = new FileInputStream("D://a.txt");
    }
}

1.这里调用f4()是ok的,原因是f4()抛出的是运行异常,运行时异常有默认处理机制;
2.java中,并不要求程序员显示处理;

public static void f3() {
		//这里调用f4()是ok的
        f4();
    }
    public static void f4() throws ArithmeticException { }

1.这里调用f4()会报错,原因是f4()抛出的是编译异常,编译异常程序员必须处理;

public static void f3() {
		//这里调用f4()会报错
        f4();
    }
    public static void f4() throws FileNotFoundException { }

🌼自定义异常

当程序中出现了某些“错误”,但该错误信息并没有在Throwable子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息;

  1. 自定义异常类名(程序员自己设计),继承Exception或者RuntimeException;
  2. 如果继承Exception,属于编译异常;
  3. 如果继承RuntimeException,属于运行异常(一般来说,继承RuntimeException)
public class CustomException_ {
    public static void main(String[] args) {
        int age = 12;
        if (!(age >= 18 && age <= 120)) {
            //这里可以通过构造器设置信息
            throw new AgeException("年龄需要在18-120之间");
        }
        System.out.println("你的年龄范围正确");
    }
}
//自定义的一个异常
class AgeException extends RuntimeException {
    //创建构造器
    public AgeException(String message) {
        super(message);
    }
}

6.throw 和 throws区别

throw在方法体内,throw后跟的是一个具体的异常对象
throws后面跟的是异常类型

-意义位置后面跟的东西
throws异常处理的一种方式方法声明处异常类型
throw手动生成异常对象的关键字方法体内异常对象

练习1

public class ThrowException {
    public static void main(String[] args) {
        try {
            methodA();
        } catch (Exception e) {
            System.out.println(e.getMessage());//(3)
        }
        methodB();
    }
    static void methodA() {
        try {
            System.out.println("进入方法A");//(1)
            throw new RuntimeException("制造异常");
        } finally {
            System.out.println("用A方法的finally");//(2)
        }
    }
    static void methodB() {
        try {
            System.out.println("进入方法B");//(4)
            return;
        } finally {
            System.out.println("调用B方法的finally");//(5)
        }
    }
}

练习2

编写方法,接受命令行的两个参数。两数相除,捕获数据格式不正确、缺少命令行参数、除数为0;

public class Homework01 {
    public static void main(String[] args) {
        //1.数组格式不正确,NumberFormatException
        //2.缺少命令行参数,ArrayIndexOutOfBoundsException
        //3.除数为0异常处理,ArithmeticException
        String[] name = args;
        try {
            if(name.length != 2) {
                throw new ArrayIndexOutOfBoundsException("命令行参数个数不对");
            }
            int num1 = Integer.parseInt(name[0]);
            int num2 = Integer.parseInt(name[1]);
            cal(num1,num2);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println(e.getMessage());
        } catch (NumberFormatException e) {
            System.out.println(e.getMessage());
        } catch (ArithmeticException e) {
            System.out.println(e.getMessage());
        }
    }
    public static double cal(int num1, int num2) {
        return num1 / num2;
    }
}

练习3

Object o = args[2] √;
Integer i = (Integer) o ×;//看他的运行类型,怎么能把String转成Integer呢?

public class Homework02 {
    public static void main(String[] args) {
        if(args[4].equals("john")) {//ArrayIndexOutOfBoundsException
            System.out.println("AA");
        } else {
            System.out.println("BB");
        }
        Object o = args[2];//string->Object 向上转型
        Integer i = (Integer) o;//向下转型 ClassCastException
        System.out.println("i=" + i);
    }
}

练习4

public class Homework03 {
    public static void main(String[] args) {
        try {
            func();
            System.out.println("A");//try代码块中的代码出现错误,那么该代码后面的一系列代码不再执行
        } catch (Exception e) {//在这里被捕获到异常,try里的代码不再执行
            System.out.println(e.getMessage());//(2)
        }
        System.out.println("D");//(3)这里输出,catch捕获到异常程序继续运行
    }
    public static void func() {
        try {
            throw new RuntimeException("出错了");//try代码块里抛出错误
        } finally {
            System.out.println("B");//(1)
        }
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~ 小团子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值