• 异常


    1 java的异常处理机制
    1.1 异常在java中以类和对象的形式存在。那么异常的继承结构是怎么样的?
    我们可以使用UML图来描述一下结构继承。
    画UML图有很多工具,例如:Rational Rose(收费的)、startUML等...
    Object
    Object下有Throwable(可抛出的)
    Throwable下有两个分支:Error(不可处理的,直接退出JVM)和Exception(可处理的)
    Exception下有两个分支:
    Exception的直接子类:编译时异常。(要求程序员在编写程序阶段必须预先对这些异常进行处理,如果不处理编译器报错,因此得名编译时异常。)
    RuntimeException:运行时异常。(在编写程序阶段程序员可以预先处理,也可以不管,都行。)

    1.2 编译时异常和运行是异常,都是发生在运行阶段。编译阶段异常是不会发生的。
    编译时异常因为什么而得名?
    因为编译时异常必须在编译(编写)阶段预先处理,如果不处理编译器报错,因此得名。
    所有一掺个都是在运行阶段发生的,因为只有程序运行阶段才可以new对象。
    因为异常的发生就是new异常对象。

    1.3 编译时异常和运行时异常的区别?
    编译时异常一般发生的概率比较高。
    运行时异常一般发生的概率比较低。
    举个例子:
    你看到外面下雨了,倾盆大雨的。
    你出门之前会预料到:如果不打伞,我可能会生病(生病是一种异常)。
    而且这个异常发生的概率很高,所以我们出门之前要拿一把伞。
    “拿一把伞”就是对“生病异常”发生之前的一种处理方式。

    对于一些发生概率较高的异常,需要在运行之前对其进行预处理。

    运行时异常一般发生的概率比较低。
    举个例子:
    小明走在大街上,可能会被天上的飞机轮子砸到。
    被飞机轮子砸到也算一种异常。
    但是这种异常发生概率较低。
    再出门之前你没必要提前对这种发生概率较低的异常进行预处理。
    如果你预处理这种异常,你将活的很累。

    假设你再出门之前,你把能够发生的异常都预先处理,你这个人会更加的安全,但是你这个人活的很累。

    假设java中没有对异常进行划分,没有分为:编译时异常和运行时异常。
    所有的异常都需要在编写阶段对其进行预处理,将是怎样的效果呢?
    首先,如果这样的话,程序肯定是绝对安全的。
    但是程序员编写程序太累,代码到处都是处理异常的代码。

    1.4 编译时异常还有其他名字:
    受检异常:CheckdException
    受控异常

    1.5 运行时异常还有其他名字:
    未受控异常:UnCheckdException
    非受控异常。

    1.6 再次强调:所有的异常都是发生在运行阶段的。

    1.7 java语言中对异常的处理包括两种方式:
    第一种方式:在方法生命的位置上,使用throws关键字,抛给上一级。
    谁调用我,我就抛给谁。抛给上一级。

    第二种方式:使用try..catch语句进行异常的捕捉。
    这件事发生了,谁也不知道,因为我给抓住了。

    举个例子:
    我是某集团的一个销售员,因为我得失误,导致公司损失了1000元,
    “损失1000元”这可以看做是一个异常发生了。我有两种处理方式,
    第一种方式:我把这件事情告诉我的领导【异常上抛】
    第二种方式:我自己掏腰包把这个钱补上。【异常的捕捉】

    什么是异常,java提供异常机制有什么用?

    package com.javase.Exception;
    /*
    1 什么是异常,java提供异常机制有什么用?
        以下程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常
        java语言是很完善的语言,提供了异常的处理方式,以下程序执行过程中出现了不正常情况,
        java把该异常信息打印输出到控制台,供程序员参考。
        程序员看到以后,可以对程序进行修改,让程序更加的健壮。
        
        什么是异常:程序执行过程中的不正常情况。
        异常的作用:增强程序的健壮性。
        
    2 以下程序执行控制台出现了:
        Exception in thread "main" java.lang.ArithmeticException: / by zero
       at com.javae.Exception.ExceptionTest01.main(ExceptionTest01.java:17)
       这个信息被我们称作:异常信息。这个信息是JVM打印的。
    */
    public class ExceptionTest01 {
        public static void main(String[] args) {
            
            int a= 10;
            int b = 1;
            // 实际上JVM在执行到此处的时候,会new异常对象。 new ArithmeticException("/ by zero");对象
            // 并且JVM将new的异常对象抛出,打印输出信息到控制台了。
            int c = a / b;
            System.out.println(a +" / "+ b + " = " + c);
            
            // 此处运行也会创建一个:ArithmeticException类型的对象。
            System.out.println(100 / 0);
            
            // 我观察到异常信息之后,对程序进行修改,更加健壮。
            /*int a = 10;
            int b = 0;
            if(b == 0){
                System.out.println("除数不能为0");
                return;
            }
            // 程序执行到此处表示除数一定不是0
            int c = a / b;
            System.out.println(a +" / "+ b + " = " + c);*/
        }
    }
    java语言中异常是以什么形式存在的呢?
    package com.javase.Exception;
    /*
    java语言中异常是以什么形式存在的呢?
        1 异常在java中以类的形式存在,每一个异常都是一个类。
        2 异常对应的现实生活中是怎样的?
            火灾(异常类):
                2008年8月8日小明家着火了(异常对象)
                2008年8月18日小刚家着火了(异常对象)
                2008年8月28日小红家着火了(异常对象)
            类是:模板。
            对象是:实际存在的个体。
            
            钱包丢了(异常类):
                2008年1月8日:小明的钱包丢了(异常对象)
                2008年1月9日:小明的钱包又丢了(异常对象)
                ...
    */
    public class ExceptionTest02 {
        public static void main(String[] args) {
            // 通过"异常类"实例化"异常对象"
            NumberFormatException numberFormatException = new NumberFormatException("数字格式化异常");
            
            // java.lang.NumberFormatException: 数字格式化异常
            System.out.println(numberFormatException);
            
            // 通过“异常类”创建“异常对象”
            NullPointerException nullPointerException = new NullPointerException("空指针异常发生了");
            // java.lang.NullPointerException: 空指针异常发生了
            System.out.println(nullPointerException);
        }
    }
    ArithmeticException异常案例:
    package com.javase.Exception;
    
    
    public class ExceptionTest03 {
        public static void main(String[] args) {
            /*
            程序执行到此处发生了ArithmeticException: / by zero异常。
            底层new了一个ArithmeticException异常对象。
            然后抛出了,由于是main方法调用了100/0
            所以这个异常ArithmeticException抛给了main方法
            main方法没有处理,将这个异常抛给了JVM。
            JVM最终终止程序的执行。
            
            ArithmeticException继承了RunTimeException,属于运行时异常。
            在编写程序阶段不需要对这种异常进行预先的处理。
             */
            System.out.println(100 / 0);
            
            // 这里的Hello World没有输出,没有执行。
            System.out.println("Hello World");
        }
    }

    分析代码异常报错原因案例:

    package com.javase.Exception;
    /*
    以下代码报错的原因是什么?
        因为doSome()方法声明位置上使用了throws ClassNotFoundException
        而ClassNotFoundException是编译时异常。必须编写代码时处理,没有处理编译器报错
    */
    public class ExceptionTest04 {
        public static void main(String[] args) {
            // main方法中调用doSome()方法
            // 因为doSome()方法声明位置上有:throws ClassNotFoundException
            // 我们在调用doSome()方法的时候必须对着汇总异常进行预先的处理。
            // 如果不处理,编译器就会报错。
            // 编译器报错信息:Unhandled exception: java.lang.ClassNotFoundException
            // doSome();
        }
        
        /**
         * doSome方法在声明的位置使用了:throws ClassNotFoundException
         * 这个代码表示doSome()方法在执行过程中,有可能会出现ClassNotFoundException异常。
         * 叫做类没有找到异常,这个异常直接父类是:Exception,所以ClassNotFoundException属于编译时异常。
         * @throws ClassNotFoundException
         */
        public static void doSome() throws ClassNotFoundException{
            System.out.println("doSome方法执行了");
        }
    }
    异常的捕捉和上抛:
    package com.javase.Exception;
    
    
    public class ExceptionTest05 {
        // 第一种处理方式:在声明的位置上继续使用:throws来完成异常的继续上抛,抛给调用者。
        // 上抛类似于推卸责任(继续向上抛给调用者)
        /*public static void main(String[] args) throws ClassNotFoundException{
            doSome();
        }*/
        
        // 第二种处理方式:try..catch进行捕捉
        // 不做等于把异常拦下了,异常真正的解决了。(调用者是不知道的。)
        public static void main(String[] args) {
            try {
                doSome();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        
        public static void doSome() throws ClassNotFoundException{
            System.out.println("doSome方法执行了");
        }
    }

    异常的上报和捕捉:

    package com.javase.Exception;
    
    
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    
    
    /*
    处理异常的第一种方式:在方法声明的位置使用throws关键字抛出,谁调用我这个方法,我就抛给谁,抛给调用者处理。
        这种处理异常的态度:上报。
        
    处理异常的第二种方式:
        使用try..catch语句对异常进行捕捉。
        这个异常不会上报,自己把这个事处理了。
        异常抛到此处为止,不在上抛了。
        
    注意:
        只要异常没有捕捉,采用上报的方式,此方法的后续代码不会执行。
        另外需要注意,try语句块中的某一行出现异常,该行后面的代码不会执行。
        try..catch执行完成后,该方法后面的java语句会执行。
    */
    public class ExceptionTest06 {
        // 一般不建议在main方法上使用throws,因为这个异常如果真正发生了,一定会抛给JVM、JVM只有终止。
        // 异常处理机制的作用就是增强程序的健壮性,怎么能做到、异常发生了也不影响程序的执行。
        // 所以一般main方法中的异常建议使用try..catch进行捕捉,main就不要继续向上抛了。
        public static void main(String[] args) {
            System.out.println("main begin");
            // try尝试
            try {
                m1();
            // 以上代码出现异常,直接进入catch语句块中执行。
            } catch (FileNotFoundException e) { // catch后面的好像一个方法的形参
                // 这个分支中可以使用e引用,e引用保存的内存地址是那个new出来异常对象的内存地址。
                // catch是捕捉 异常之后走的分支
                // 在catch分支中干什么?处理异常。
                System.out.println("文件不存在,可能路径错误!也可能该文件被删除了。");
                System.out.println(e);// java.io.FileNotFoundException: C:哇哈哈哈哈哈哈哈哈.txt (拒绝访问。)
            }
            // try..catch把异常抓住以后,这里的代码会继续执行。
            System.out.println("main end");
            
        }
        
        public static void m1() throws FileNotFoundException {
            System.out.println("m1 begin");
            m2();
            // 出现异常以下代码不会被执行
            System.out.println("m1 end");
        }
        
        // 抛别的不行,抛ClassCastException说明你还是没有对FileNOtFoundException进行处理
        // 抛FileNotFoundException的父类对象IOException,这样是可以的。因为IOException包括FileNotFoundException
        // private static void m2() throws FileNotFoundException {
        // 这样也可以,因为Exception包括所有的异常。
        // private static void m2() throws Exception {
        // throws后面也可以写多个异常,使用逗号隔开
        // private static void m2() throws ClassNotFoundException,FileNotFoundException{
        private static void m2() throws FileNotFoundException{
            System.out.println("m2 begin");
            m3();
            // 出现异常以下代码不会被执行
            System.out.println("m2 end");
        }
        
        private static void m3() throws FileNotFoundException {
            // 调用SUN jdk中某个类的构造方法
            // 这个类还没有接触过,后期IO流的时候就知道了。
            // 我们只是借助这个类学习一下异常处理机制。
            // 创建一个输入流对象,该流指向一个文件。
            System.out.println("m3 begin");
            /*
            编译报错的原因是什么?
                1 第一:这里调用了一个构造方法:FileInputStream(String name)
                2 第二:这个构造方法的声明位置上有:throws FileNotFoundException
                3 第三:通过类的继承结构看到:FileNotFoundException的父类是IOException,IOException的父类是Exception
                最终得知,FileNotFoundException是编译时异常。
                
                错误原因?编译时异常要求程序员编写程序阶段必须对他进行处理,不处理编译器报错。
                
             */
            // 我们采用第一种处理方式:在方法声明的位置上使用throws继续上抛。
            // new FileOutputStream("C:\Users\xlWu\Desktop\学习\异常\学习.txt");
            new FileOutputStream("C:哇哈哈哈哈哈哈哈哈.txt");
            // 出现异常以下代码不会被执行
            System.out.println("m1 end");
        }
    }
    深入try..catch:
    package com.javase.Exception;
    
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    
    
    /*
    深入try..catch
        1 catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型。
        2 catch可以写多个,建议catch的时候,精确的一个一个处理,这样有利于程序的调试。
        3 catch写多个的时候,从上到下,必须遵循从小到大。
        
    在以后的开发中,处理编译时异常,应该上报还是捕捉呢,怎么选?
        如果希望调用者来处理,选择throws上报。
        其它情况使用捕捉的方式。
    */
    public class ExceptionTest07 {
        /*public static void main(String[] args) throws Exception, FileNotFoundException,NullPointerException,NumberFormatException {
        
        }*/
        
        /*public static void main(String[] args) throws Exception {
        
        }*/
        
        public static void main(String[] args) {
            /*try {
                FileInputStream fis =  new FileInputStream("D:\Users\xlWu\Desktop\学习\异常\异常的继承结构图.uml");
                System.out.println("出现异常,这里无法执行!");
            } catch (FileNotFoundException e) {
                System.out.println("文件不存在!");
            }
        
            System.out.println("hello world!");*/
        
            /*try {
                FileInputStream fis =  new FileInputStream("D:\Users\xlWu\Desktop\学习\异常\异常的继承结构图.uml");
                System.out.println("出现异常,这里无法执行!");
            *//*} catch (IOException e) {// 多态 IOException e = new FileNotFoundException();*//*
            } catch (Exception e) {// 多态 Exception e = new FileNotFoundException();
                System.out.println("文件不存在!");
            }*/
        
            /*try {
                // 创建输入流
                FileInputStream fis =  new FileInputStream("D:\Users\xlWu\Desktop\学习\异常\异常的继承结构图.uml");
                // 读文件
                fis.read();
            } catch (Exception e) { // 所有的异常都走这个分支
                System.out.println("文件不存在!");
            }*/
        
            /*try {
                // 创建输入流
                FileInputStream fis =  new FileInputStream("D:\Users\xlWu\Desktop\学习\异常\异常的继承结构图.uml");
                // 读文件
                fis.read();
            } catch (FileNotFoundException e) {
                System.out.println("文件不存在!");
            } catch (IOException e) {
                System.out.println("读文件报错了!");
            }*/
            
            // 编译报错  自上而下执行  必须由小到大
            /*try {
                // 创建输入流
                FileInputStream fis =  new FileInputStream("D:\Users\xlWu\Desktop\学习\异常\异常的继承结构图.uml");
                // 读文件
                fis.read();
            } catch (IOException e) {
                System.out.println("文件不存在!");
            } catch (FileNotFoundException e) {
                System.out.println("读文件报错了!");
            }*/
            
            // JDK8的新特性
            try {
                // 创建输入流
                FileInputStream fis =  new FileInputStream("D:\Users\xlWu\Desktop\学习\异常\异常的继承结构图.uml");
                // 进行数学运算
                System.out.println(10 / 0);// 这个是运行时异常,编写程序时可以处理,也可以不处理。
            } catch (FileNotFoundException | ArithmeticException | NullPointerException e) {
                System.out.println("文件不存在?数学异常?空指针异常?都有可能!");
            }
        }
    }
     
     
  • 相关阅读:
    Zabbix使用grafana展示图形
    Jumpserver堡垒机
    ELK之使用filebeat的多行过滤插件把多行合并成一行
    [0] Enterprise Architect
    [0] LoadRunner
    [0] Axure
    [0] MVC&MVP&MVVM差异点
    [0] 传统架构与领域模式架构对比
    [转] .NET领域驱动设计—看DDD是如何运用设计模式颠覆传统架构
    [转] .NET领域驱动设计—实践(穿过迷雾走向光明)
  • 原文地址:https://www.cnblogs.com/xlwu/p/13257922.html
Copyright © 2020-2023  润新知