【入坑Java第七天】

异常机制

异常概述

  • 在Java语言中,将程序执行中发生的不正常情况称为“异常”。异常是程序中的一些错误,但不是所以的错误都是异常,并且错误有时候是不可避免的。

异常分类

  • 从继承结构中可以看到Object下有一个Throwable,在Throwable下有两个子类。Error表示错误,在java中发生错误是无法处理的,例如:内存溢出错误OutOfMemoryError等。Exception表示异常,异常是可以处理的,异常发生之后有两个结果,1:程序终止执行,2:处理完异常继续执行。

  • 在Exception下有两大类,Exception子类(受控异常/编译时异常),RuntimeException(非受控异常/运行时异常)。所有的编译时异常要求在程序编写阶段预先处理,如果不处理编译器会报错。

常见的异常

  • NullPointerException空指针异常类

  • ClassNotFoundException指定的类不存在

  • NumberFormatException字符串转换为数字异常

  • ArrayIndexOutOfBoundsException数组下标越界异常

  • IllegalArgumentException方法的参数错误

  • IllegalAccessException没有访问权限

  • ArithmeticException数学运算异常

  • ClassCastException数据类型转换异常

  • FileNotFoundException文件未找到异常

  • ArrayStoreException数组存储异常

  • NoSuchMethodException方法不存在异常

  • InstantiationException实例化异常

  • OutOfMemoryException 内存不足错误

  • .NoClassDefFoundException 未找到类定义错误

  • ......

try-catch捕捉

  • 以下程序没有使用异常机制:

    public class Test {
        public static void main(String[] args) {
    ​
            int[] arr = new int[]{10,20,30,40,50,0,60,70,80,90};
    ​
            for (int i=0;i<arr.length;i++){
                    int val = 100 / arr[i];
                    System.out.println("100/"+arr[i]+"=" + val);
            }
    ​
        }
    }
    ​
    运行结果:
    100/10=10
    100/20=5
    100/30=3
    100/40=2
    100/50=2
    Exception in thread "main" java.lang.ArithmeticException: / by zero
        at Test.main(Test.java:7)
  • 通过以上程序发现当一个地方出现了错误,程序就停止执行。接下来使用异常机制try-catch捕捉执行以上代码:

    public class Test {
        public static void main(String[] args) {
    ​
            int[] arr = new int[]{10,20,30,40,50,0,60,70,80,90};
    ​
            for (int i=0;i<arr.length;i++){
                try{
                    int val = 100 / arr[i];
                    System.out.println("100/"+arr[i]+"=" + val);
                }catch(Exception e){
                    System.out.println("100/"+arr[i]+",出现异常");
                }
            }
    ​
        }
    }
    ​
    运行结果:
    100/10=10
    100/20=5
    100/30=3
    100/40=2
    100/50=2
    100/0,出现异常
    100/60=1
    100/70=1
    100/80=1
    100/90=1
  • 如果想要知道捕捉的异常是什么,可以使用以下方式:

    public class Test {
        public static void main(String[] args) {
    ​
            int[] arr = new int[]{10,20,30,40,50,0,60,70,80,90};
    ​
            for (int i=0;i<arr.length;i++){
                try{
                    int val = 100 / arr[i];
                    System.out.println("100/"+arr[i]+"=" + val);
                }catch(Exception e){
                    // 使用这一句可以知道捕捉了什么异常
                    e.printStackTrace();
                }
            }
    ​
        }
    }
    ​
    运行结果:
    100/10=10
    100/20=5
    100/30=3
    100/40=2
    100/50=2
    100/60=1
    100/70=1
    100/80=1
    100/90=1
    java.lang.ArithmeticException: / by zero
        at Test.main(Test.java:8)
  • 以上程序捕捉了ArithmeticException异常,这是一个算术运算异,例如:一个整数除以零。

  • 如果异常代码块发生异常,异常代码块外的程序会不会执行:

    public class Test {
        public static void main(String[] args) {
    ​
            int[] arr = new int[10];
    ​
            try{
                System.out.println("arr数组第十一个元素 = " + arr[11]);
            }catch(Exception e){
                e.printStackTrace();
            }
    ​
            // 异常代码块发生异常之后,这里的程序会不会执行!
            System.out.println("hello world!");
    ​
        }
    }
    ​
    运行结果:
    java.lang.ArrayIndexOutOfBoundsException: Index 11 out of bounds for length 10
        at Test.main(Test.java:7)
    hello world!
  • 从以上程序可以发现,异常代码块中发生了异常,之外的程序可以执行。

finally语句块

  • finally语句块必须和try语句块联合使用,不能独立使用,放在finally语句块中的程序是必须执行的。

    public class Test {
        public static void main(String[] args) {
    ​
            int[] arr = new int[10];
    ​
            try{
                System.out.println("arr数组第十一个元素 = " + arr[11]);
            }catch(Exception e){
                e.printStackTrace();
            }finally {
                System.out.println("finally语句块执行了!");
            }
            
    ​
        }
    }
    ​
    运行结果:
    java.lang.ArrayIndexOutOfBoundsException: Index 11 out of bounds for length 10
        at Test.main(Test.java:7)
    finally语句块执行了!
  • 无论try语句块中有没有发生异常,finally语句块都必须执行。一般finally语句块经常用来关闭流\资源,流\资源是非常宝贵的,用完之后必须要关闭,如果不关闭会导致内存泄漏。

    public class Test {
        public static void main(String[] args) {
    ​
            FileWriter out = null;
    ​
            try {
                // 创建一个标准输出流
                out = new FileWriter("");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }finally {
                try {
                    // 关闭流的方法,需要处理异常
                    out.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
    ​
        }
    }

如何自定义异常

  • 异常类要么继承RuntimeException(非受控异常)或者继承Exception(受控异常),然后提供一个无参构造方法和一个带有String参数的构造方法。

  • 接下来自定义一个登录失败的异常(自定义异常时需要判断继承哪个异常):

    public class LoginException extends RuntimeException{
        public LoginException(){
            
        }
        public LoginException(String s){
            super(s);
        }
    }

手动抛出异常

  • 异常发生需要new异常对象,使用throw关键字将异常抛出。结合上面自定义登录失败异常,写一个简单案例:

    public class TestLogin {
        /**
         * 模拟登录程序
         * @param args
         */
        public static void main(String[] args) {
            // 准备一个用户名和密码
            String user = "123456";
            String pwd = "abc";
    ​
            Scanner scanner = new Scanner(System.in);
    ​
            // 输入用户名和密码
            String uuser = scanner.next().trim();
            String ppwd = scanner.next().trim();
            
            if (!(user.equals(uuser) && pwd.equals(ppwd))){
                // 手动抛出异常
                throw new LoginException("登录失败!");
            }
    ​
            System.out.println("登录成功!");
        }
    }
    ​
    运行结果1:
    123456
    abc
    登录成功!
        
    运行结果2:
    123456
    aaa
    Exception in thread "main" com.bj.servlet.LoginException: 登录失败!
        at com.bj.servlet.TestLogin.main(TestLogin.java:22)

声明异常

  • 使用throws用来声明以便抛出,throws只能出现在方法声明的位置上,意思是将异常继续上抛给调用程序来处理。

    public class Test {
        public static void main(String[] args) throws Exception{ // 声明异常
    ​
            // 创建流
            FileWriter out = new FileWriter("");
            // 关闭流
            out.close();
            
        }
    }
  • 假设某个公司有3个员工,普通员工犯了错误处理不了,上抛给经理,如果经理处理不了,继续上抛给董事长,如果董事长也处理不了,公司倒闭\相当于程序结束。

  • try catch捕捉异常,被捕捉的异常在当前程序被处理掉,throws上抛异常,自己不处理,如果一直不处理一直上抛,最终抛到JVM(java虚拟机),如果JVM也处理不了,程序结束。

final , finalize , finally的区别

  • final是一个关键字,用来修饰类,方法,变量等,表示最终的,不可变的。

  • finalize是Object类中的一个方法名,属于标识符。

  • finally是一个关键字,属于异常处理机制,finally必须联合try一起使用。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值