zoukankan      html  css  js  c++  java
  • Java——异常

      Java 的异常机制主要依赖于try 、catch 、finally 、throw 和 throws 五个关键字,其中 try 关键字后紧跟一个花括号括起来的代码块(花括号不能省略),简称 try 块,它里面放置可能引发异常代码。 catch 后对应异常类型和一个代码块,用于表明该 catch 块用于处理这种类型代码块 。 多个 catch 块后还可以跟一个 finally 块,finally块用于回收在 try 块里打开的物理资源,异常机制会保证 finally 块总会被执行。 throws 关键字主要在方法签名中使用,用于声明该方法可能抛出的异常;而 throw 用于抛出一个实际的异常, throw 可以单独作为语句使用,抛出一个具体异常对象。

    演示程序中异常:

    public static void main(String[] args) {
            Scanner input =new Scanner(System.in);
            System.out.println("请输入被除数:");
            int num1=input.nextInt();
            System.out.println("请输入被除数:");
            int num2= input.nextInt();
            System.out.println(String.format("%d /%d =%d", num1,num2,num1/num2));
            System.out.println("感谢使用本程序!");
    
        }

      在正常情况下,用户会按照系统的提示输入整数,除数不为 0 ,运行结果如下:

        

    但是用户没按照要求进行输入,如被除数输入了“B”,则程序运行时将会发生异常,运行如下:

    或者输入 0,则程序运行时也将发生异常,运行如图:

    从结果我们可以看出一旦出现异常,程序将会立刻结束,不仅计算机和输出商的语句不被执行,而且输出“感谢使用本程序!” 的语句也不执行。那么我们该如何解决异常呢?如果我们用 if ——else语句来对各种异常情况进行来处理。我们会发现代码加入了大量的异常情况判断和处理代码,把很大一部分时间放在了处理异常代码上,放在了“堵漏洞”上,减少了编写业务代码的时间,必然影响开发效率。

      那么同样一段代码,把可能出现异常的代码放入 try 语句块中,并使用 catch 语句块捕获异常。

    public static void main(String[] args) {
            Scanner input =new Scanner(System.in);
            System.out.println("请输入被除数:");
            int num1=input.nextInt();
            try {
                System.out.println("请输入被除数:");
                int num2= input.nextInt();
                System.out.println(String.format("%d /%d =%d", num1,num2,num1/num2));
                System.out.println("感谢使用本程序!");
            } catch (Exception e) {
                System.out.println("出现错误:被除数和除数必须是整数,"+"除数不能为0");
                e.printStackTrace();
            }
        }

     再次输入以上的三种情况,

    第一种:

    第二种:

    第三种:

    如果希望无论是否发生异常,都执行输出“感谢使用蹦本程序!” 的语句,,那么只需要在 try——catch 语句块后加 finally 块,把该语句放入finally 块,无论发生异常,finally 开中的代码总能被执行。

    public static void main(String[] args) {
            Scanner input =new Scanner(System.in);
            System.out.println("请输入被除数:");
            int num1=input.nextInt();
            try {
                System.out.println("请输入被除数:");
                int num2= input.nextInt();
                System.out.println(String.format("%d /%d =%d", num1,num2,num1/num2));
                
            } catch (Exception e) {
                System.out.println("出现错误:被除数和除数必须是整数,"+"除数不能为0");
                e.printStackTrace();
            }
            finally{
                System.out.println("感谢使用本程序!");
            }
        }

     结果:

     即使在 try 块和 catch 块中存在 return 语句,finally 块中语句也会被执行。

    public static void main(String[] args) {
            Scanner input =new Scanner(System.in);
            System.out.println("请输入被除数:");
            int num1=input.nextInt();
            try {
                System.out.println("请输入被除数:");
                int num2= input.nextInt();
                System.out.println(String.format("%d /%d =%d", num1,num2,num1/num2));
                return;     //finally语句块仍旧会被执行
            } catch (Exception e) {
                System.out.println("出现错误:被除数和除数必须是整数,"+"除数不能为0");
                return; //finally语句块仍旧会被执行
            }
            finally{
                System.out.println("感谢使用本程序!");
            }
        }

    执行顺序:执行 try 块或 catch 中之前的语句,执行 finally 块中的语句,执行 try 块或 catch 中的 return 语句退出。

    运行结果: 

    finally 块中语句不被执行的唯一情况:在异常处理代码中执行System.exit(1),将退出Java虚拟机。

    public static void main(String[] args) {
            Scanner input =new Scanner(System.in);
            System.out.println("请输入被除数:");
            int num1=input.nextInt();
            try {
                System.out.println("请输入被除数:");
                int num2= input.nextInt();
                System.out.println(String.format("%d /%d =%d", num1,num2,num1/num2));
            } catch (Exception e) {
                System.out.println("出现错误:被除数和除数必须是整数,"+"除数不能为0");
                System.exit(1);
            }
            finally{
                System.out.println("感谢使用本程序!");
            }
        }

    运行结果:

     

    》多重catch块

      一段代码可能会引发多种类型异常,这时,可以在一个 try 语句块后面跟多个 catch 语句块,分别处理不同的异常。但排列顺序必须是从子类到父类,最后一个一般都是Execption 类,因为所有异常子类都继承自 Exception类,所以如果将父类异常放到前面,那么所有的异常都将被捕获,后面 catch 块中的子类异常讲的不到被执行的机会。当运行时,系统冲上到下分别对每个 catch 语句块处理的异常的异常类型进行检测,并执行第一个与异常类型匹配的 catch语句。执行其中的一条 catch 语句之后,其后的 catch 语句都将被忽略。

    public static void main(String[] args) {
            Scanner input =new Scanner(System.in);
            System.out.println("请输入被除数:");
            int num1=input.nextInt();
            try {
                System.out.println("请输入被除数:");
                int num2= input.nextInt();
                System.out.println(String.format("%d /%d =%d", num1,num2,num1/num2));
                
            } catch (InputMismatchException e) {
                System.err.println("被除数和除数必须是整数。");
            }catch (ArithmeticException e) {
                System.err.println("除数不能为零。");
            } catch (Exception e) {
                System.err.println("其它未知。");
            }finally{
                System.out.println("感谢使用本程序!");
            }
        }

    运行结果:

     》声明异常——throws

       如果一个方法体中抛出异常,我们就希望调用者能及时地捕获异常,那么如何通知调用着呢?Java 语言中通过关键字 throws 声明某个方法可能抛出的各种异常,throws 可以抛出多个异常,之间用逗号隔开。

    public static void main(String[] args) {
    
            try {
                divide();
    
            } catch (Exception e) {
                System.err.println("出现错误:被除数和除数必须是整数" + "除数不能为零");
    
            } finally {
                System.out.println("感谢使用本程序!");
            }
        }
    
        public static void divide() throws Exception {
            Scanner input = new Scanner(System.in);
            System.out.println("请输入被除数:");
            int num1 = input.nextInt();
            System.out.println("请输入被除数:");
            int num2 = input.nextInt();
            System.out.println(String.format("%d /%d =%d", num1, num2, num1 / num2));
        }

       从上面看出 divide() 方法使用 throws 声明抛出了异常,并在 main 方法里面调用了此方法,通过 try —— catch 捕获了异常。如果不通过 try ——catch 处理异常,我们可以继续使用 throws 抛出异常

    public static void main(String[] args) throws Exception {
    
                divide();
    
        }
    
        public static void divide() throws Exception {
            Scanner input = new Scanner(System.in);
            System.out.println("请输入被除数:");
            int num1 = input.nextInt();
            System.out.println("请输入被除数:");
            int num2 = input.nextInt();
            System.out.println(String.format("%d /%d =%d", num1, num2, num1 / num2));
        }

       但是使用这种方法需要注意:调用者抛出的异常一定要比被调用抛出的异常更大或等于。

    》抛出异常——throw

      除了系统自动抛出异常,在编程过程中,我们往往遇到这样的情形:有些问题是系统无法自动发现并解决的,如年龄不在正长范围内、性别输入不是 “男” 或 “女” 等,此时需要程序员而不是系统来自动抛出异常,把问题提交给调用者去解决。

    》使用 throw 在方法内抛出异常
    public class Person {
    
        private String sex;
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) throws Exception {
            if ("".equals(sex) || "".equals(sex)) {
                this.sex = sex;
            } else {
                throw new Exception("性别必须是"男"或者"女"!");
            }
        }
    
    }
    public static void main(String[] args) throws Exception {
    
            Person person = new Person();
            person.setSex("hao");
        }

    输出结果:

     throw 和 throws 的区别表现在以下三个方面。

      》作用不同 : throw 用于在程序中抛出异常;throws 用于声明在该方法内抛出了异常。

      》使用位置不同:throw 位于方法体内部,可以作为单独语句使用;throws 必须跟在方法参数列表的后面,不能单独使用。

      》内容不同:throw 抛出一个异常对象,而且只能是一个;throws 后面跟异常类,而且可以跟多个以异常类。

    》异常的分类

      Throwable 类 :所有异常类型都是 Throwable 类的子类,它派生两个子类,即Error 和 Exception 。

      Error类 :表示紧靠程序本身无法恢复的严重错误,如内存溢出动态链接失败、虚拟机错误。应用程序不应该抛出这种类型的对象(一般是由虚拟机抛出)。假如出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以在进行程序设计时,应该更关注Exception类。

      Exception 类:由Java 应用程序抛出和处理的严重错误,如需文件找不到、网络连接不通或中断。算术运算出错(如被零除)、数组下标越界、装载了一个不存在的类、对 null 对象的操作、类型转换异常类等。他的各种不同的子类分别对应不同类型的异常。

      运行时异常:包括RuntimeException 及其所有子类,不要求程序必须对它们做出处理。

      Checked 异常(非运行时异常):除了运行时异常外的其他由Exception 继承来的异常类。程序必须捕获或者声明抛出这种异常,否则会出现编译错误,无法通过编译。处理方式包括来钟:通过 try——catch 在当前位置捕获并处理异常;通过throws 声明抛出异常,交给上一级调用方法处理。

    》自定义异常

      当 JDK 中的异常类型不能满足出现的需要时,可以自定义异常类。

    public class GenderException extends Exception {
    
        public GenderException() {
            super();
        }
    
        public GenderException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public GenderException(String message) {
            super(message);
        }
    
        public GenderException(Throwable cause) {
            super(cause);
        }
    
    }
    public class Person {
    
        private String sex;
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) throws Exception {
            if ("".equals(sex) || "".equals(sex)) {
                this.sex = sex;
            } else {
                throw new GenderException("性别必须是"男"或者"女"!");
            }
        }
    
    }
  • 相关阅读:
    搭建docker私有registory (harbor)
    消息队列原理及ActiveMQ、RocketMQ、RabbitMQ、Kafka区别总结
    too many users are authenticated
    docker环境部署nginx、tomcat、redis
    docekr环境部署mysql、kafaka、kafkamanager和mongodb
    在IE6 情况下让PNG图片透明的3种方法
    ecshop商品列表页出现一个空的搜索结果
    ecshop去掉国家省市区,实现手动填写收货地址
    ecshop始终显示全部分类
    ecshop商品列表页增加/显示货号SN
  • 原文地址:https://www.cnblogs.com/szj-ang/p/7324795.html
Copyright © 2011-2022 走看看