• 异常Exception



    【疑点】

    带有finally的语句执行顺序
    

    1.异常概述

    程序运行的过程中的非正常状况,与错误(Error)不同,Error是程序无法处理的状况,异常是可以通过程序来解决的状况,Exception与Error都是Throwable的直接子类
    
    任何程序都有可能出现大量的问题或者异常,如果不对程序进行异常的处理,程序会在出现异常的代码处中断执行,导致程序无法继续。
    
    异常存在的意义:让我们的程序在出现异常的代码之后还能够继续执行,而不至于直接中断后面代码的执行
    
    1.1 Throwable类
    Throwable是Java中所有异常和错误的基类,位于java.lang包下
    --| Error 错误:硬件异常,虚拟机异常,执行逻辑错误
    --| Exception 异常:程序在执行期间或配置中发生错误,可处理
    
    构造方法:
    	Throwable();
    		创建一个Throwable类对象,其中保存的异常或者错误信息为null
    	Throwable(String message); 【重点】
    		创建一个Throwable类对象,其中保存的异常或者错误信息为message
    
    成员方法:	
    	String toString();
    		得到当前异常的简要信息描述
    	String getMessage();
    		获取当前Throwable类对象中保存的异常或者错误信息
    	void printStackTrace();	【伪重点】
        	在命令行中展示错误的前因后果!!!红色字体
    
    1.2 Error和Exception
    Error 错误
    	无法处理,只能避免!!!
    	错误都是Error结尾
    Exception 异常
    	可以处理,还有挽回的余地
    	异常都是Exception结尾
    【举例】	
    Java代码中有一个数组需要申请64GB内存,(目前电脑内存32GB)
    	不可能!!!错误 Error
    
    Java中代码需要一个数组,但是给予的操作不合法
    	可以处理的,Exception
    	
    Exception:Exception是所有异常的根
    --| RuntimeException(非检测异常):运行期异常,可处理可不处理,可通过编译
    --| CheckException(受查异常,检测异常):必须处理,不处理不能编译
    
        检测异常:编译期间就要求处理的异常,后者try~catch,要么throws声明异常;
        File f = new File();
        f.creatNewFile();//此处会报警
    

    1.3 异常五个关键字

    try:尝试执行一段有可能发生异常的代码
    
    catch:捕获,发生异常后要处理的代码块
    
    finally:最终,不管是否发生异常,该代码块都将被执行
    
    throws:异常的声明,在方法的头部要声明该方法中可能出现的所有异常对象
    
    throw:在方法中出现异常是将异常交给下一个主调方法来处理
    

    1. 异常处理

    1.1 Exception的两种处理方式概述
    小门诊
    	手指划伤,需要包扎处理,当场处理好
    	发烧去小门诊,不敢接,要不您去指定发烧医院
    
    当场处理好,拒之门外。
    	这两种方式就是Java中处理异常的方式
    	【捕获】 有能力处理你就捕获,自己的问题你就捕获
    	【抛出】 没有办法处理,或者不是自己的问题,和自己无关,因别人导致的错误,抛出
    	
    	捕获 try~~catch
    	抛出 throw在语句块处,throws在声明处
    	
    
    1.2 捕获异常
    1.2.1 基本格式
    格式:
    	try {
    		// 有可能出现问题的代码,存在一定隐患的代码
    	} catch (异常类型) {
    		// 对应当前异常类型的处理方式
    		// 【因为技术所限,我们只能sout 或者 printStackTrace 后期我们会使用日志log】
    	}
    
    public class Demo1 {
    	public static void main(String[] args) {
    		int num1 = 0;
    		int num2 = 20;
    		
    		int ret = 0;
    		
    		/*
    		 * num2 / num1 是存在一定的隐患的,如果num1保存的数据是0,
    		 * 这里会出现一个算术异常
    		 */
    		try {
    			// 有可能出现异常的代码
    			ret = num2 / num1;
    		} catch (ArithmeticException e) {
    			/*
    			 * ArithmeticException 算术异常,catch块中捕获对应异常
    			 * catch大括号内是对应的处理方式,现在只能展示效果
    			 */
    			e.printStackTrace();
    		}
    		
    		System.out.println(ret);
    		
    		/*
    		 * java.lang.ArithmeticException: / by zero
    		 * 			at com.qfedu.a_exception.Demo1.main(Demo1.java:16)
    		 * 0
    		 */
    	}
    }
    
    1.2.2 细节问题和注意事项
    1. 代码中出现异常,JVM会终止代码运行,如果使用try catch捕获处理异常,JVM会认为当前代码中不存在异常,可以继续运行。
    	【类比】球员受伤,下场处理,处理完毕,回到场上
    
    2. 在try大括号内或者catch大括号内都是局部变量,处理操作数据时小心谨慎。
    
    3. try - catch捕获处理异常,可以处理多种异常情况!!!而且建议异常处理分门别类,对症下药
    
    4. 代码中存在多种隐患,存在多个异常情况,try - catch捕获有且只能处理第一个出现异常的代码,因为JVM从异常代码开始直接进入异常捕获阶段
    
    5. Exception作为Java中所有异常的超类,在捕获异常处理时如果直接使用Exception进行捕获处理,无法做到异常对症下药操作。
    
    6. Exception可以作为try - catch 最后一个,用于处理其他异常捕获之后没有对症方式遗留问题。[不多见]
    
    7. 捕获多个异常时,无继承关系的异常没有上下排列要求,有继承关系时需要子类异常在上,父类异常在下
    
    8.两个相同的catch捕获时,下面的那个会成为unreachable code
    
    9.异常的类型(try部分)和(catch部分)不匹配时,catch部分不会捕获不匹配的异常(try部分)
    
    1.3 抛出异常
    1.3.1 基本格式
    关键字:
    	throw
    		在方法内特定条件下抛出指定异常
    	throws
    		在【方法声明】位置,【形式参数列表之后】,告知调用者,当前方法有哪些异常抛出
    
    	用于处理非当前方法操作问题,导致出现的异常,一般情况下是用于处理方法运行过程中因为参数传入,参数处理,运算结果导致的问题,抛出异常。
    	throw是一个高级的参数合法性判断!!!
    
    /*                                                      
     * throws 关键字在方法声明位置告知当前方法的调用者,这里存在异常信息                 
     */                                                     
    /**                                                     
     * 测试方法                                                 
     *                                                      
     * @param num1 int类型参数                                  
     * @param num2 int类型参数                                  
     * @throws ArithmeticException 如果除数为0,当前方法抛出算术异常        
     */                                                     
    public static void test(int num1, int num2)             
    		throws ArithmeticException {                    
    	                                                    
    	/*                                                  
    	参数合法性判断 之前的方式 low                                   
    	if (0 == num2) {                                    
    		System.out.println("你个瘪犊子...坑我");               
    		System.exit(0);                                 
    	}                                                   
    	*/                                                  
    	// 参数合法性判断,如果num2 为0, 这里存在隐患                        
    	if (0 == num2) {                                    
    		/*                                              
    		 * 存在异常,这里创建一个异常对象抛出,这里构造方法中                    
    		 * 存在无参数构造方法和有参数构造方法                            
    		 * 无参数构造方法异常信息为null                             
    		 * 有参数构造方法可以传入一个String类型数据,异常信息为指定字符串内容         
    		 */                                             
    		throw new ArithmeticException("除数不能为0");        
    	}                                                   
    	                                                    
    	// 如果num2的值为0,num1 / num2 操作是存在隐患的,有问题的             
    	int ret = num1 / num2;                              
    	System.out.println(ret);                            
    }                                                        	
    
    1.3.2finally
    无论上面是否有异常finally都会执行,通常用于:
    	1.释放资源
    	2.无论是否异常都需执行的代码
    
    finally 和return的执行顺序。return可以加载try和finall的模块中,不能加在finally中,加在finally中会警告
    

    finally执行顺序

    package exception;
    
    public class TryCatchFinally04 {
    
    	public static void main(String[] args) {
    		System.out.println(getNum());
    	}
    	
    	/**
    	 * try catch中return的变量,即使该变量在finally代码块中做了修改,
    	 * 	但是return的瞬间点的值是多少,我们该方法最终的返回值还是当时瞬间点的值。
    	 * 
    	 * @return
    	 */
    	public static int getNum() {
    		int a = 0;
    		try {
    			return a;
    		} catch (Exception e) {
    			e.printStackTrace();
    			return -a;
    		}finally {
    			a++;
    			//return ++a;
    		}
    		//return 0;
    	}
    }
    
    
    0
    
    package exception;
    
    public class TryCatchFinally03 {
    
    	public static void main(String[] args) {
    		System.out.println(getNum());
    	}
    	
    	/**
    	 * finally的代码块会在try或者catch的return之前执行
    	 * 	假如finally中存在return,则整个方法的返回值就是finally的代码的return值
    	 * @return
    	 */
    	public static int getNum() {
    		try {
    			System.out.println("try");
    			System.out.println(1 / 0);
    			//return 1;
    		} catch (Exception e) {
    			System.out.println("catch");
    			e.printStackTrace();
    			//return -1;
    		}finally {
    			System.out.println("finally");
    		}
    		return 0;
    	}
    }
    
    1.3.3 细节问题和注意事项
    1. 代码如果运行到throw抛出异常,之后的代码不再运行,之后的代码是成为无参触及代码
    
    2. 代码中存在多种隐患,按照隐含的情况,分门别类处理,不能在同一个条件内抛出两个异常。并且在方法的声明位置,throws之后,不同的异常,使用逗号隔开
    
    3. 当调用带有异常抛出的方法时,对于方法抛出的异常,有两种处理方式,可以捕获处理,也可以抛出处理。
    
    1.4 抛出处理和捕获处理选择
    情况分析:
    	用户查询指定路径指定名字的文件,存在的异常处理分析过程
    
    5d1bf4191abd3e040b11c071882f2198.png
    1.5 异常分类
    运行时异常:
    	RuntimeException 代码运行过程中出现的异常,没有强制处理的必要性
            ArrayIndexOutOfBoundsException 数组下标越界异常
            NullPointerException 空指针异常
            ArithmeticException 算术异常
    	
    	运行时异常不强制要求捕获和抛出!!!
    	JVM会处理RuntimeException,也就是告知异常的前因后果!!!
    	
    其他异常:
    	强制要求处理,不管是捕获处理,还是抛出处理,都需要进行操作。
    	如果未处理!!!直接报错!!!
    	
    	IDE工具的快速修复
    		Eclipse  Ctrl + 1
    		IDEA Alt + Enter
    
    1.6 自定义异常
    业务逻辑存在需求,但是Java中没有合适的异常来描述对应情况,自定义异常
    	
    自定义异常格式:
    	class MyException extends Exception {
    		// 无参数构造方法
    		public MyException() {}
    		
    		// 有参数构造方法,且参数数据类型为String类型
    		public MyException(String message) {
    			super(message);
    		}
    	}
    	
    RuntimeException和Exception选择:
    	根据业务需求选择是否需要抛出
    【注意】
    	Eclipse会提示要求完成一个ID号,可以忽略,存在一个警告,不用管。
    
    package exception;
    
    public class CustomException {
    	public static void main(String[] args) {
    		Student s = new Student();
    		try {
    			s.setAge(60);
    		} catch (AgeException e) {
    			System.out.println("年龄必须在0~200之间");
    			System.out.println(e.toString());//得到异常的简要信息描述,来自于Throwable
    			System.out.println(e.getMessage());//得到异常的简要信息描述,来自于Throwable
    			e.printStackTrace();
    		}
    		
    		s.setSex("afds");
    		System.out.println("程序结束");
    		
    	}
    }
    
    /**
     * 自定义异常: 定义有参无参构造方法,有参构造方法在【自行抛出异常位置】可以增加提示信息
     * 在【捕获异常】处增加e.printStackTrace()可以说输出提示信息
     * 自定义异常会要求完成一个异常,可以忽略,存在一个报警,不用管
     * 定义学生年龄的受查异常
     */
    class AgeException extends Exception {
    	// 定义无参构造方法
    	public AgeException() {
    	}
    
    	/**
    	 * 异常的有参构造,需要的参数是String类型的参数
    	 * @param message 异常的提示信息
    	 */
    	public AgeException(String message) {
    		/*
    		 * 通过super关键字调用父类的构造方法
    		 */
    		super(message);
    	}
    }
    
    /*
     * 定义学生性别运行时异常
     * 
     * SexException继承的是运行异常,在代码块中只抛出异常不在声明处进行声明不会报警
     * 如果继承的是受查异常,只抛出不声明不会存在异常
     */
    class SexException extends RuntimeException {
    	public SexException() {
    	}
    
    	public SexException(String message) {
    		super(message);
    	}
    }
    
    class Student {
    	private int age;
    	private String sex;
    
    	public void setAge(int age) throws AgeException {
    		if (age > 200) {
    			throw new AgeException("年龄输入非法");
    		}
    		this.age = age;
    	}
    
    	public void setSex(String sex) {
    		if (!(sex.equals("男") || sex.equals("女"))) {
    			throw new SexException("性别输入非法");
    		} else {
    			this.sex = sex;
    		}
    	}
    }
    
    1.7 异常处理总结
    1. 异常存在的必要性,代码中使用的数据,大多数来源于用户,用户传入数据是一个非常不可靠的情况!!!存在一定错误意识,反馈机制和处理机制。
    2. 异常处理方式 
    	捕获
    	抛出
    	要根据使用情况,操作方式,反馈形式来选择对应的处理方式。
    3. 自定义异常,了解异常的构造,基本上在开发中用到自定义异常的情况不多见。但是要了解关于异常信息保存的方式。
    
    1.8 接口,继承下的异常
    方法名,返回值类型,参数列表和父类相同
    子类访问修饰符比父类更大
    子类(实现类)中的方法异常不能比父类(接口)更宽
    

    【请简述你对异常的理解】

    异常是程序运行时的意外情况。
    异常位于java.lang包下,继承自Throwable类,为所有异常的基类。
    程序运行时不发生异常情况时不可能的,程序发生异常时会停止运行,不能完成对应的服务。对于程序中的异常,我们可以通过一些对应的处理措施可以预防这种情况,在程序发生异常时还能继续运行下去,完成应有的功能。
    异常可分为运行时异常和受查异常,受查异常在程序进行编写时就有错误提示,我们可以马上发现并进行修正。运行时异常需要我们了解程序运行情况,对可能出现问题的程序进行捕获或者声明。
    程序在用户界面可能发生异常时要进行捕获处理,不能将异常展现给用户;在非用户界面,我们根据实际情况对异常进行捕获,抛出或者修正异常。
    
  • 相关阅读:
    Nginx Record
    Go 查找元素
    博客转移公告
    模板库
    模板库
    【BZOJ2276】Temperature
    【BZOJ3524】Couriers
    【BZOJ4458】GTY的OJ
    AtCoder Grand Contest 007
    Editing 2011-2012 ACM-ICPC Northeastern European Regional Contest (NEERC 11)
  • 原文地址:https://www.cnblogs.com/raising/p/12969246.html
Copyright © 2020-2023  润新知